Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Mar 2017 16:38:39 +0000 (UTC)
From:      Dmitry Chagin <dchagin@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r315312 - in stable/11/sys: compat/cloudabi compat/linux dev/iscsi_initiator kern netinet sys
Message-ID:  <201703151638.v2FGcdOK038038@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dchagin
Date: Wed Mar 15 16:38:39 2017
New Revision: 315312
URL: https://svnweb.freebsd.org/changeset/base/315312

Log:
  MFC r305093 (by mjg@):
  
  fd: add fdeget_locked and use in kern_descrip
  
  MFC r305756 (by oshogbo@):
  
  fd: add fget_cap and fget_cap_locked primitives.
  They can be used to obtain capabilities along with a referenced fp.
  
  MFC r306174 (by oshogbo@):
  
  capsicum: propagate rights on accept(2)
  
  Descriptor returned by accept(2) should inherits capabilities rights from
  the listening socket.
  
  PR:           201052
  
  MFC r306184 (by oshogbo@):
  
  fd: simplify fgetvp_rights by using fget_cap_locked.
  
  MFC r306225 (by mjg@):
  
  fd: fix up fgetvp_rights after r306184
  
  fget_cap_locked returns a referenced file, but the fgetvp_rights does
  not need it. Instead, due to the filedesc lock being held, it can
  ref the vnode after the file was looked up.
  
  Fix up fget_cap_locked to be consistent with other _locked helpers and not
  ref the file.
  
  This plugs a leak introduced in r306184.
  
  MFC r306232 (by oshogbo@):
  
  fd: fix up fget_cap
  
  If the kernel is not compiled with the CAPABILITIES kernel options
  fget_unlocked doesn't return the sequence number so fd_modify will
  always report modification, in that case we got infinity loop.
  
  MFC r311474 (by glebius@):
  
  Use getsock_cap() instead of fgetsock().
  
  MFC r312079 (by glebius@):
  
  Use getsock_cap() instead of deprecated fgetsock().
  
  MFC r312081 (by glebius@):
  
  Use getsock_cap() instead of deprecated fgetsock().
  
  MFC r312087 (by glebius@):
  
  Remove deprecated fgetsock() and fputsock().
  
  Bump __FreeBSD_version as getsock_cap changed and
  fgetsock/fputsock pair removed.

Modified:
  stable/11/sys/compat/cloudabi/cloudabi_sock.c
  stable/11/sys/compat/linux/linux_socket.c
  stable/11/sys/dev/iscsi_initiator/isc_soc.c
  stable/11/sys/dev/iscsi_initiator/iscsi.c
  stable/11/sys/kern/kern_descrip.c
  stable/11/sys/kern/kern_sendfile.c
  stable/11/sys/kern/uipc_syscalls.c
  stable/11/sys/netinet/sctp_syscalls.c
  stable/11/sys/sys/file.h
  stable/11/sys/sys/filedesc.h
  stable/11/sys/sys/param.h
  stable/11/sys/sys/socketvar.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/cloudabi/cloudabi_sock.c
==============================================================================
--- stable/11/sys/compat/cloudabi/cloudabi_sock.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/compat/cloudabi/cloudabi_sock.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -210,7 +210,7 @@ cloudabi_sys_sock_stat_get(struct thread
 	int error;
 
 	error = getsock_cap(td, uap->sock, cap_rights_init(&rights,
-	    CAP_GETSOCKOPT, CAP_GETPEERNAME, CAP_GETSOCKNAME), &fp, NULL);
+	    CAP_GETSOCKOPT, CAP_GETPEERNAME, CAP_GETSOCKNAME), &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;

Modified: stable/11/sys/compat/linux/linux_socket.c
==============================================================================
--- stable/11/sys/compat/linux/linux_socket.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/compat/linux/linux_socket.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -775,6 +775,7 @@ linux_connect(struct thread *td, struct 
 	cap_rights_t rights;
 	struct socket *so;
 	struct sockaddr *sa;
+	struct file *fp;
 	u_int fflag;
 	int error;
 
@@ -792,24 +793,23 @@ linux_connect(struct thread *td, struct 
 	 * Linux doesn't return EISCONN the first time it occurs,
 	 * when on a non-blocking socket. Instead it returns the
 	 * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
-	 *
-	 * XXXRW: Instead of using fgetsock(), check that it is a
-	 * socket and use the file descriptor reference instead of
-	 * creating a new one.
 	 */
-	error = fgetsock(td, args->s, cap_rights_init(&rights, CAP_CONNECT),
-	    &so, &fflag);
-	if (error == 0) {
-		error = EISCONN;
-		if (fflag & FNONBLOCK) {
-			SOCK_LOCK(so);
-			if (so->so_emuldata == 0)
-				error = so->so_error;
-			so->so_emuldata = (void *)1;
-			SOCK_UNLOCK(so);
-		}
-		fputsock(so);
+	error = getsock_cap(td, args->s, cap_rights_init(&rights, CAP_CONNECT),
+	    &fp, &fflag, NULL);
+	if (error != 0)
+		return (error);
+
+	error = EISCONN;
+	so = fp->f_data;
+	if (fflag & FNONBLOCK) {
+		SOCK_LOCK(so);
+		if (so->so_emuldata == 0)
+			error = so->so_error;
+		so->so_emuldata = (void *)1;
+		SOCK_UNLOCK(so);
 	}
+	fdrop(fp, td);
+
 	return (error);
 }
 
@@ -855,7 +855,7 @@ linux_accept_common(struct thread *td, i
 		if (error == EFAULT && namelen != sizeof(struct sockaddr_in))
 			return (EINVAL);
 		if (error == EINVAL) {
-			error1 = getsock_cap(td, s, &rights, &fp, NULL);
+			error1 = getsock_cap(td, s, &rights, &fp, NULL, NULL);
 			if (error1 != 0)
 				return (error1);
 			so = fp->f_data;

Modified: stable/11/sys/dev/iscsi_initiator/isc_soc.c
==============================================================================
--- stable/11/sys/dev/iscsi_initiator/isc_soc.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/dev/iscsi_initiator/isc_soc.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -680,7 +680,6 @@ isc_stop_receiver(isc_session_t *sp)
 
      if(sp->fp != NULL)
 	  fdrop(sp->fp, sp->td);
-     fputsock(sp->soc);
      sp->soc = NULL;
      sp->fp = NULL;
 

Modified: stable/11/sys/dev/iscsi_initiator/iscsi.c
==============================================================================
--- stable/11/sys/dev/iscsi_initiator/iscsi.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/dev/iscsi_initiator/iscsi.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -388,20 +388,14 @@ i_setsoc(isc_session_t *sp, int fd, stru
      if(sp->soc != NULL)
 	  isc_stop_receiver(sp);
 
-     error = fget(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT), &sp->fp);
+     error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT),
+	     &sp->fp, NULL, NULL);
      if(error)
 	  return error;
 
-     error = fgetsock(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT),
-        &sp->soc, 0);
-     if(error == 0) {
-	  sp->td = td;
-	  isc_start_receiver(sp);
-     }
-     else {
-	  fdrop(sp->fp, td);
-	  sp->fp = NULL;
-     }
+     sp->soc = sp->fp->f_data;
+     sp->td = td;
+     isc_start_receiver(sp);
 
      return error;
 }

Modified: stable/11/sys/kern/kern_descrip.c
==============================================================================
--- stable/11/sys/kern/kern_descrip.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/kern/kern_descrip.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/resourcevar.h>
 #include <sys/sbuf.h>
 #include <sys/signalvar.h>
-#include <sys/socketvar.h>
 #include <sys/kdb.h>
 #include <sys/stat.h>
 #include <sys/sx.h>
@@ -517,28 +516,26 @@ kern_fcntl(struct thread *td, int fd, in
 		break;
 
 	case F_GETFD:
+		error = EBADF;
 		FILEDESC_SLOCK(fdp);
-		if (fget_locked(fdp, fd) == NULL) {
-			FILEDESC_SUNLOCK(fdp);
-			error = EBADF;
-			break;
+		fde = fdeget_locked(fdp, fd);
+		if (fde != NULL) {
+			td->td_retval[0] =
+			    (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
+			error = 0;
 		}
-		fde = &fdp->fd_ofiles[fd];
-		td->td_retval[0] =
-		    (fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0;
 		FILEDESC_SUNLOCK(fdp);
 		break;
 
 	case F_SETFD:
+		error = EBADF;
 		FILEDESC_XLOCK(fdp);
-		if (fget_locked(fdp, fd) == NULL) {
-			FILEDESC_XUNLOCK(fdp);
-			error = EBADF;
-			break;
+		fde = fdeget_locked(fdp, fd);
+		if (fde != NULL) {
+			fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
+			    (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
+			error = 0;
 		}
-		fde = &fdp->fd_ofiles[fd];
-		fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
-		    (arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
 		FILEDESC_XUNLOCK(fdp);
 		break;
 
@@ -2450,6 +2447,82 @@ finit(struct file *fp, u_int flag, short
 }
 
 int
+fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
+    struct file **fpp, struct filecaps *havecapsp)
+{
+	struct filedescent *fde;
+	int error;
+
+	FILEDESC_LOCK_ASSERT(fdp);
+
+	fde = fdeget_locked(fdp, fd);
+	if (fde == NULL) {
+		error = EBADF;
+		goto out;
+	}
+
+#ifdef CAPABILITIES
+	error = cap_check(cap_rights_fde(fde), needrightsp);
+	if (error != 0)
+		goto out;
+#endif
+
+	if (havecapsp != NULL)
+		filecaps_copy(&fde->fde_caps, havecapsp, true);
+
+	*fpp = fde->fde_file;
+
+	error = 0;
+out:
+	return (error);
+}
+
+int
+fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
+    struct file **fpp, struct filecaps *havecapsp)
+{
+	struct filedesc *fdp = td->td_proc->p_fd;
+	int error;
+#ifndef CAPABILITIES
+	error = fget_unlocked(fdp, fd, needrightsp, fpp, NULL);
+	if (error == 0 && havecapsp != NULL)
+		filecaps_fill(havecapsp);
+#else
+	struct file *fp;
+	seq_t seq;
+
+	for (;;) {
+		error = fget_unlocked(fdp, fd, needrightsp, &fp, &seq);
+		if (error != 0)
+			return (error);
+
+		if (havecapsp != NULL) {
+			if (!filecaps_copy(&fdp->fd_ofiles[fd].fde_caps,
+			    havecapsp, false)) {
+				fdrop(fp, td);
+				goto get_locked;
+			}
+		}
+
+		if (!fd_modified(fdp, fd, seq))
+			break;
+		fdrop(fp, td);
+	}
+
+	*fpp = fp;
+	return (0);
+
+get_locked:
+	FILEDESC_SLOCK(fdp);
+	error = fget_cap_locked(fdp, fd, needrightsp, fpp, havecapsp);
+	if (error == 0)
+		fhold(*fpp);
+	FILEDESC_SUNLOCK(fdp);
+#endif
+	return (error);
+}
+
+int
 fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
     struct file **fpp, seq_t *seqp)
 {
@@ -2712,30 +2785,31 @@ fgetvp_rights(struct thread *td, int fd,
     struct filecaps *havecaps, struct vnode **vpp)
 {
 	struct filedesc *fdp;
+	struct filecaps caps;
 	struct file *fp;
-#ifdef CAPABILITIES
 	int error;
-#endif
 
 	fdp = td->td_proc->p_fd;
-	fp = fget_locked(fdp, fd);
-	if (fp == NULL || fp->f_ops == &badfileops)
-		return (EBADF);
-
-#ifdef CAPABILITIES
-	error = cap_check(cap_rights(fdp, fd), needrightsp);
+	error = fget_cap_locked(fdp, fd, needrightsp, &fp, &caps);
 	if (error != 0)
 		return (error);
-#endif
-
-	if (fp->f_vnode == NULL)
-		return (EINVAL);
+	if (fp->f_ops == &badfileops) {
+		error = EBADF;
+		goto out;
+	}
+	if (fp->f_vnode == NULL) {
+		error = EINVAL;
+		goto out;
+	}
 
+	*havecaps = caps;
 	*vpp = fp->f_vnode;
 	vrefact(*vpp);
-	filecaps_copy(&fdp->fd_ofiles[fd].fde_caps, havecaps, true);
 
 	return (0);
+out:
+	filecaps_free(&caps);
+	return (error);
 }
 
 int
@@ -2763,61 +2837,6 @@ fgetvp_write(struct thread *td, int fd, 
 #endif
 
 /*
- * Like fget() but loads the underlying socket, or returns an error if the
- * descriptor does not represent a socket.
- *
- * We bump the ref count on the returned socket.  XXX Also obtain the SX lock
- * in the future.
- *
- * Note: fgetsock() and fputsock() are deprecated, as consumers should rely
- * on their file descriptor reference to prevent the socket from being free'd
- * during use.
- */
-int
-fgetsock(struct thread *td, int fd, cap_rights_t *rightsp, struct socket **spp,
-    u_int *fflagp)
-{
-	struct file *fp;
-	int error;
-
-	*spp = NULL;
-	if (fflagp != NULL)
-		*fflagp = 0;
-	if ((error = _fget(td, fd, &fp, 0, rightsp, NULL)) != 0)
-		return (error);
-	if (fp->f_type != DTYPE_SOCKET) {
-		error = ENOTSOCK;
-	} else {
-		*spp = fp->f_data;
-		if (fflagp)
-			*fflagp = fp->f_flag;
-		SOCK_LOCK(*spp);
-		soref(*spp);
-		SOCK_UNLOCK(*spp);
-	}
-	fdrop(fp, td);
-
-	return (error);
-}
-
-/*
- * Drop the reference count on the socket and XXX release the SX lock in the
- * future.  The last reference closes the socket.
- *
- * Note: fputsock() is deprecated, see comment for fgetsock().
- */
-void
-fputsock(struct socket *so)
-{
-
-	ACCEPT_LOCK();
-	SOCK_LOCK(so);
-	CURVNET_SET(so->so_vnet);
-	sorele(so);
-	CURVNET_RESTORE();
-}
-
-/*
  * Handle the last reference to a file being closed.
  */
 int

Modified: stable/11/sys/kern/kern_sendfile.c
==============================================================================
--- stable/11/sys/kern/kern_sendfile.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/kern/kern_sendfile.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -502,7 +502,7 @@ sendfile_getsock(struct thread *td, int 
 	 * The socket must be a stream socket and connected.
 	 */
 	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SEND),
-	    sock_fp, NULL);
+	    sock_fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	*so = (*sock_fp)->f_data;

Modified: stable/11/sys/kern/uipc_syscalls.c
==============================================================================
--- stable/11/sys/kern/uipc_syscalls.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/kern/uipc_syscalls.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -89,20 +89,23 @@ static int sockargs(struct mbuf **, char
 /*
  * Convert a user file descriptor to a kernel file entry and check if required
  * capability rights are present.
+ * If required copy of current set of capability rights is returned.
  * A reference on the file entry is held upon returning.
  */
 int
 getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
-    struct file **fpp, u_int *fflagp)
+    struct file **fpp, u_int *fflagp, struct filecaps *havecapsp)
 {
 	struct file *fp;
 	int error;
 
-	error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL);
+	error = fget_cap(td, fd, rightsp, &fp, havecapsp);
 	if (error != 0)
 		return (error);
 	if (fp->f_type != DTYPE_SOCKET) {
 		fdrop(fp, td);
+		if (havecapsp != NULL)
+			filecaps_free(havecapsp);
 		return (ENOTSOCK);
 	}
 	if (fflagp != NULL)
@@ -201,7 +204,7 @@ kern_bindat(struct thread *td, int dirfd
 	AUDIT_ARG_FD(fd);
 	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
 	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;
@@ -262,7 +265,7 @@ sys_listen(td, uap)
 
 	AUDIT_ARG_FD(uap->s);
 	error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error == 0) {
 		so = fp->f_data;
 #ifdef MAC
@@ -335,6 +338,7 @@ kern_accept4(struct thread *td, int s, s
 	struct file *headfp, *nfp = NULL;
 	struct sockaddr *sa = NULL;
 	struct socket *head, *so;
+	struct filecaps fcaps;
 	cap_rights_t rights;
 	u_int fflag;
 	pid_t pgid;
@@ -345,7 +349,7 @@ kern_accept4(struct thread *td, int s, s
 
 	AUDIT_ARG_FD(s);
 	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT),
-	    &headfp, &fflag);
+	    &headfp, &fflag, &fcaps);
 	if (error != 0)
 		return (error);
 	head = headfp->f_data;
@@ -358,7 +362,8 @@ kern_accept4(struct thread *td, int s, s
 	if (error != 0)
 		goto done;
 #endif
-	error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0);
+	error = falloc_caps(td, &nfp, &fd,
+	    (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
 	if (error != 0)
 		goto done;
 	ACCEPT_LOCK();
@@ -467,6 +472,8 @@ noconnection:
 	 * a reference on nfp to the caller on success if they request it.
 	 */
 done:
+	if (nfp == NULL)
+		filecaps_free(&fcaps);
 	if (fp != NULL) {
 		if (error == 0) {
 			*fp = nfp;
@@ -545,7 +552,7 @@ kern_connectat(struct thread *td, int di
 	AUDIT_ARG_FD(fd);
 	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
 	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;
@@ -805,7 +812,7 @@ kern_sendit(td, s, mp, flags, control, s
 		AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
 		cap_rights_set(&rights, CAP_CONNECT);
 	}
-	error = getsock_cap(td, s, &rights, &fp, NULL);
+	error = getsock_cap(td, s, &rights, &fp, NULL, NULL);
 	if (error != 0) {
 		m_freem(control);
 		return (error);
@@ -1013,7 +1020,7 @@ kern_recvit(td, s, mp, fromseg, controlp
 
 	AUDIT_ARG_FD(s);
 	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;
@@ -1328,7 +1335,7 @@ sys_shutdown(td, uap)
 
 	AUDIT_ARG_FD(uap->s);
 	error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_SHUTDOWN),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error == 0) {
 		so = fp->f_data;
 		error = soshutdown(so, uap->how);
@@ -1402,7 +1409,7 @@ kern_setsockopt(td, s, level, name, val,
 
 	AUDIT_ARG_FD(s);
 	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error == 0) {
 		so = fp->f_data;
 		error = sosetopt(so, &sopt);
@@ -1483,7 +1490,7 @@ kern_getsockopt(td, s, level, name, val,
 
 	AUDIT_ARG_FD(s);
 	error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error == 0) {
 		so = fp->f_data;
 		error = sogetopt(so, &sopt);
@@ -1544,7 +1551,7 @@ kern_getsockname(struct thread *td, int 
 
 	AUDIT_ARG_FD(fd);
 	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;
@@ -1643,7 +1650,7 @@ kern_getpeername(struct thread *td, int 
 
 	AUDIT_ARG_FD(fd);
 	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 	so = fp->f_data;

Modified: stable/11/sys/netinet/sctp_syscalls.c
==============================================================================
--- stable/11/sys/netinet/sctp_syscalls.c	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/netinet/sctp_syscalls.c	Wed Mar 15 16:38:39 2017	(r315312)
@@ -121,17 +121,18 @@ sys_sctp_peeloff(td, uap)
 	} */ *uap;
 {
 #if (defined(INET) || defined(INET6)) && defined(SCTP)
-	struct file *nfp = NULL;
+	struct file *headfp, *nfp = NULL;
 	struct socket *head, *so;
 	cap_rights_t rights;
 	u_int fflag;
 	int error, fd;
 
 	AUDIT_ARG_FD(uap->sd);
-	error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
-	    &head, &fflag);
+	error = getsock_cap(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
+	    &headfp, &fflag, NULL);
 	if (error != 0)
 		goto done2;
+	head = headfp->f_data;
 	if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
 		error = EOPNOTSUPP;
 		goto done;
@@ -196,7 +197,7 @@ noconnection:
 done:
 	if (nfp != NULL)
 		fdrop(nfp, td);
-	fputsock(head);
+	fdrop(headfp, td);
 done2:
 	return (error);
 #else  /* SCTP */
@@ -248,7 +249,7 @@ sys_sctp_generic_sendmsg (td, uap)
 	}
 
 	AUDIT_ARG_FD(uap->sd);
-	error = getsock_cap(td, uap->sd, &rights, &fp, NULL);
+	error = getsock_cap(td, uap->sd, &rights, &fp, NULL, NULL);
 	if (error != 0)
 		goto sctp_bad;
 #ifdef KTRACE
@@ -361,7 +362,7 @@ sys_sctp_generic_sendmsg_iov(td, uap)
 	}
 
 	AUDIT_ARG_FD(uap->sd);
-	error = getsock_cap(td, uap->sd, &rights, &fp, NULL);
+	error = getsock_cap(td, uap->sd, &rights, &fp, NULL, NULL);
 	if (error != 0)
 		goto sctp_bad1;
 
@@ -477,7 +478,7 @@ sys_sctp_generic_recvmsg(td, uap)
 
 	AUDIT_ARG_FD(uap->sd);
 	error = getsock_cap(td, uap->sd, cap_rights_init(&rights, CAP_RECV),
-	    &fp, NULL);
+	    &fp, NULL, NULL);
 	if (error != 0)
 		return (error);
 #ifdef COMPAT_FREEBSD32

Modified: stable/11/sys/sys/file.h
==============================================================================
--- stable/11/sys/sys/file.h	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/sys/file.h	Wed Mar 15 16:38:39 2017	(r315312)
@@ -50,8 +50,6 @@ struct thread;
 struct uio;
 struct knote;
 struct vnode;
-struct socket;
-
 
 #endif /* _KERNEL */
 
@@ -268,10 +266,6 @@ int fgetvp_read(struct thread *td, int f
 int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp,
     struct vnode **vpp);
 
-int fgetsock(struct thread *td, int fd, cap_rights_t *rightsp,
-    struct socket **spp, u_int *fflagp);
-void fputsock(struct socket *sp);
-
 static __inline int
 _fnoop(void)
 {

Modified: stable/11/sys/sys/filedesc.h
==============================================================================
--- stable/11/sys/sys/filedesc.h	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/sys/filedesc.h	Wed Mar 15 16:38:39 2017	(r315312)
@@ -190,6 +190,11 @@ int	getvnode(struct thread *td, int fd, 
 	    struct file **fpp);
 void	mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
 
+int	fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
+	    struct file **fpp, struct filecaps *havecapsp);
+int	fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
+	    struct file **fpp, struct filecaps *havecapsp);
+
 /* Return a referenced file from an unlocked descriptor. */
 int	fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
 	    struct file **fpp, seq_t *seqp);
@@ -207,6 +212,18 @@ fget_locked(struct filedesc *fdp, int fd
 	return (fdp->fd_ofiles[fd].fde_file);
 }
 
+static __inline struct filedescent *
+fdeget_locked(struct filedesc *fdp, int fd)
+{
+
+	FILEDESC_LOCK_ASSERT(fdp);
+
+	if ((u_int)fd > fdp->fd_lastfile)
+		return (NULL);
+
+	return (&fdp->fd_ofiles[fd]);
+}
+
 static __inline bool
 fd_modified(struct filedesc *fdp, int fd, seq_t seq)
 {

Modified: stable/11/sys/sys/param.h
==============================================================================
--- stable/11/sys/sys/param.h	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/sys/param.h	Wed Mar 15 16:38:39 2017	(r315312)
@@ -58,7 +58,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1100509	/* Master, propagated to newvers */
+#define __FreeBSD_version 1100510	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Modified: stable/11/sys/sys/socketvar.h
==============================================================================
--- stable/11/sys/sys/socketvar.h	Wed Mar 15 16:16:30 2017	(r315311)
+++ stable/11/sys/sys/socketvar.h	Wed Mar 15 16:38:39 2017	(r315312)
@@ -321,6 +321,7 @@ extern u_long	sb_max;
 extern so_gen_t so_gencnt;
 
 struct file;
+struct filecaps;
 struct filedesc;
 struct mbuf;
 struct sockaddr;
@@ -340,7 +341,7 @@ struct uio;
  */
 int	getsockaddr(struct sockaddr **namp, caddr_t uaddr, size_t len);
 int	getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
-	    struct file **fpp, u_int *fflagp);
+	    struct file **fpp, u_int *fflagp, struct filecaps *havecaps);
 void	soabort(struct socket *so);
 int	soaccept(struct socket *so, struct sockaddr **nam);
 void	soaio_enqueue(struct task *task);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703151638.v2FGcdOK038038>