Date: Mon, 21 Jan 2008 16:19:01 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 133789 for review Message-ID: <200801211619.m0LGJ1Tx050803@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=133789 Change 133789 by rwatson@rwatson_freebsd_capabilities on 2008/01/21 16:18:42 Implement capability checks for many common socket system calls. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/sys/kern/uipc_syscalls.c#2 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/sys/kern/uipc_syscalls.c#2 (text+ko) ==== @@ -36,11 +36,13 @@ __FBSDID("$FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.263 2008/01/13 14:44:09 attilio Exp $"); #include "opt_sctp.h" +#include "opt_capabilities.h" #include "opt_compat.h" #include "opt_ktrace.h" #include "opt_mac.h" #include <sys/param.h> +#include <sys/capability.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/lock.h> @@ -106,6 +108,7 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0, "Number of sendfile(2) sf_bufs in use"); +#if 0 /* * Convert a user file descriptor to a kernel file entry. A reference on the * file entry is held upon returning. This is lighter weight than @@ -142,8 +145,60 @@ *fpp = fp; return (error); } +#endif /* + * Convert a user file descriptor to a kernel file entry and check that, if + * it is a capability, the right rights are present. A reference on the file + * entry is held upon returning. + */ +static int +getsock_cap(struct filedesc *fdp, int fd, cap_rights_t rights, + struct file **fpp, u_int *fflagp) +{ + struct file *fp; + int error; + + fp = NULL; + if (fdp == NULL) { + *fpp = NULL; + return (EBADF); + } + FILEDESC_SLOCK(fdp); + fp = fget_locked(fdp, fd); + if (fp == NULL) { + error = EBADF; + goto out; + } + + /* + * If the file descriptor is for a capability, test rights and use + * the file descriptor referenced by the capability. + */ +#ifdef CAPABILITIES + if (fp->f_type == DTYPE_CAPABILITY) { + error = cap_fget(fp, rights, &fp); + if (error) { + fp = NULL; + goto out; + } + } +#endif /* CAPABILITIES */ + if (fp->f_vnode == NULL) { + error = EINVAL; + fp = NULL; + goto out; + } else { + fhold(fp); + error = 0; + } +out: + FILEDESC_SUNLOCK(fdp); + *fpp = fp; + return (error); +} + +/* * System call interface to the socket abstraction. */ #if defined(COMPAT_43) @@ -218,7 +273,7 @@ struct file *fp; int error; - error = getsock(td->td_proc->p_fd, fd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL); if (error) return (error); so = fp->f_data; @@ -250,7 +305,8 @@ struct file *fp; int error; - error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_LISTEN, &fp, + NULL); if (error == 0) { so = fp->f_data; #ifdef MAC @@ -345,7 +401,7 @@ } fdp = td->td_proc->p_fd; - error = getsock(fdp, s, &headfp, &fflag); + error = getsock_cap(fdp, s, CAP_ACCEPT, &headfp, &fflag); if (error) return (error); head = headfp->f_data; @@ -530,7 +586,7 @@ int error; int interrupted = 0; - error = getsock(td->td_proc->p_fd, fd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL); if (error) return (error); so = fp->f_data; @@ -732,11 +788,15 @@ struct socket *so; int i; int len, error; + cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif - error = getsock(td->td_proc->p_fd, s, &fp, NULL); + rights = CAP_WRITE; + if (mp->msg_name != NULL) + rights |= CAP_CONNECT; + error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL); if (error) return (error); so = (struct socket *)fp->f_data; @@ -931,7 +991,7 @@ if(controlp != NULL) *controlp = 0; - error = getsock(td->td_proc->p_fd, s, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, s, CAP_READ, &fp, NULL); if (error) return (error); so = fp->f_data; @@ -1242,7 +1302,8 @@ struct file *fp; int error; - error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_SHUTDOWN, &fp, + NULL); if (error == 0) { so = fp->f_data; error = soshutdown(so, uap->how); @@ -1304,7 +1365,7 @@ panic("kern_setsockopt called with bad valseg"); } - error = getsock(td->td_proc->p_fd, s, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, s, CAP_SHUTDOWN, &fp, NULL); if (error == 0) { so = fp->f_data; error = sosetopt(so, &sopt); @@ -1382,7 +1443,7 @@ panic("kern_getsockopt called with bad valseg"); } - error = getsock(td->td_proc->p_fd, s, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, s, CAP_GETSOCKOPT, &fp, NULL); if (error == 0) { so = fp->f_data; error = sogetopt(so, &sopt); @@ -1443,7 +1504,8 @@ if (*alen < 0) return (EINVAL); - error = getsock(td->td_proc->p_fd, fd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETSOCKNAME, &fp, + NULL); if (error) return (error); so = fp->f_data; @@ -1536,7 +1598,8 @@ if (*alen < 0) return (EINVAL); - error = getsock(td->td_proc->p_fd, fd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETPEERNAME, &fp, + NULL); if (error) return (error); so = fp->f_data; @@ -1809,8 +1872,8 @@ * The socket must be a stream socket and connected. * Remember if it a blocking or non-blocking socket. */ - if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp, - NULL)) != 0) + if ((error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_WRITE, + &sock_fp, NULL)) != 0) goto out; so = sock_fp->f_data; if (so->so_type != SOCK_STREAM) { @@ -2306,6 +2369,7 @@ #endif struct uio auio; struct iovec iov[1]; + cap_rights_t rights; if (uap->sinfo) { error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); @@ -2313,15 +2377,19 @@ return (error); u_sinfo = &sinfo; } + + rights = CAP_WRITE; if (uap->tolen) { error = getsockaddr(&to, uap->to, uap->tolen); if (error) { to = NULL; goto sctp_bad2; } + rights |= CAP_CONNECT; } - error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL); + /* XXXRW: Is this use of rights right for SCTP? */ + error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL); if (error) goto sctp_bad; @@ -2405,6 +2473,7 @@ #endif struct uio auio; struct iovec *iov, *tiov; + cap_rights_t rights; if (uap->sinfo) { error = copyin(uap->sinfo, &sinfo, sizeof (sinfo)); @@ -2412,15 +2481,17 @@ return (error); u_sinfo = &sinfo; } + rights = CAP_WRITE; if (uap->tolen) { error = getsockaddr(&to, uap->to, uap->tolen); if (error) { to = NULL; goto sctp_bad2; } + rights |= CAP_CONNECT; } - error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL); if (error) goto sctp_bad1; @@ -2516,7 +2587,7 @@ #ifdef KTRACE struct uio *ktruio = NULL; #endif - error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL); + error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_READ, &fp, NULL); if (error) { return (error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801211619.m0LGJ1Tx050803>