Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Sep 2016 09:58:46 +0000 (UTC)
From:      Mariusz Zaborski <oshogbo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r306174 - in head/sys: compat/cloudabi compat/linux kern netinet sys
Message-ID:  <201609220958.u8M9wkfh034759@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: oshogbo
Date: Thu Sep 22 09:58:46 2016
New Revision: 306174
URL: https://svnweb.freebsd.org/changeset/base/306174

Log:
  capsicum: propagate rights on accept(2)
  
  Descriptor returned by accept(2) should inherits capabilities rights from
  the listening socket.
  
  PR:		201052
  Reviewed by:	emaste, jonathan
  Discussed with:	many
  Differential Revision:	https://reviews.freebsd.org/D7724

Modified:
  head/sys/compat/cloudabi/cloudabi_sock.c
  head/sys/compat/linux/linux_socket.c
  head/sys/kern/kern_sendfile.c
  head/sys/kern/uipc_syscalls.c
  head/sys/netinet/sctp_syscalls.c
  head/sys/sys/socketvar.h

Modified: head/sys/compat/cloudabi/cloudabi_sock.c
==============================================================================
--- head/sys/compat/cloudabi/cloudabi_sock.c	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/compat/cloudabi/cloudabi_sock.c	Thu Sep 22 09:58:46 2016	(r306174)
@@ -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: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/compat/linux/linux_socket.c	Thu Sep 22 09:58:46 2016	(r306174)
@@ -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: head/sys/kern/kern_sendfile.c
==============================================================================
--- head/sys/kern/kern_sendfile.c	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/kern/kern_sendfile.c	Thu Sep 22 09:58:46 2016	(r306174)
@@ -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: head/sys/kern/uipc_syscalls.c
==============================================================================
--- head/sys/kern/uipc_syscalls.c	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/kern/uipc_syscalls.c	Thu Sep 22 09:58:46 2016	(r306174)
@@ -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)
@@ -188,7 +191,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;
@@ -235,7 +238,7 @@ sys_listen(struct thread *td, struct lis
 
 	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
@@ -308,6 +311,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;
@@ -318,7 +322,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;
@@ -331,7 +335,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();
@@ -440,6 +445,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;
@@ -511,7 +518,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;
@@ -754,7 +761,7 @@ kern_sendit(struct thread *td, int s, st
 		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)
 		return (error);
 	so = (struct socket *)fp->f_data;
@@ -923,7 +930,7 @@ kern_recvit(struct thread *td, int s, st
 
 	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;
@@ -1198,7 +1205,7 @@ sys_shutdown(struct thread *td, struct s
 
 	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);
@@ -1257,7 +1264,7 @@ kern_setsockopt(struct thread *td, int s
 
 	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);
@@ -1323,7 +1330,7 @@ kern_getsockopt(struct thread *td, int s
 
 	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);
@@ -1376,7 +1383,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;
@@ -1463,7 +1470,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: head/sys/netinet/sctp_syscalls.c
==============================================================================
--- head/sys/netinet/sctp_syscalls.c	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/netinet/sctp_syscalls.c	Thu Sep 22 09:58:46 2016	(r306174)
@@ -248,7 +248,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 +361,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 +477,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: head/sys/sys/socketvar.h
==============================================================================
--- head/sys/sys/socketvar.h	Thu Sep 22 09:33:22 2016	(r306173)
+++ head/sys/sys/socketvar.h	Thu Sep 22 09:58:46 2016	(r306174)
@@ -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?201609220958.u8M9wkfh034759>