Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Aug 2011 12:30:23 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r224778 - in head: sys/amd64/linux32 sys/cddl/compat/opensolaris/sys sys/compat/freebsd32 sys/compat/linux sys/compat/svr4 sys/dev/aac sys/dev/amr sys/dev/hwpmc sys/dev/ipmi sys/dev/isc...
Message-ID:  <201108111230.p7BCUNnS092831@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Thu Aug 11 12:30:23 2011
New Revision: 224778
URL: http://svn.freebsd.org/changeset/base/224778

Log:
  Second-to-last commit implementing Capsicum capabilities in the FreeBSD
  kernel for FreeBSD 9.0:
  
  Add a new capability mask argument to fget(9) and friends, allowing system
  call code to declare what capabilities are required when an integer file
  descriptor is converted into an in-kernel struct file *.  With options
  CAPABILITIES compiled into the kernel, this enforces capability
  protection; without, this change is effectively a no-op.
  
  Some cases require special handling, such as mmap(2), which must preserve
  information about the maximum rights at the time of mapping in the memory
  map so that they can later be enforced in mprotect(2) -- this is done by
  narrowing the rights in the existing max_protection field used for similar
  purposes with file permissions.
  
  In namei(9), we assert that the code is not reached from within capability
  mode, as we're not yet ready to enforce namespace capabilities there.
  This will follow in a later commit.
  
  Update two capability names: CAP_EVENT and CAP_KEVENT become
  CAP_POST_KEVENT and CAP_POLL_KEVENT to more accurately indicate what they
  represent.
  
  Approved by:	re (bz)
  Submitted by:	jonathan
  Sponsored by:	Google Inc

Modified:
  head/sys/amd64/linux32/linux32_machdep.c
  head/sys/cddl/compat/opensolaris/sys/file.h
  head/sys/compat/freebsd32/freebsd32_ioctl.c
  head/sys/compat/linux/linux_file.c
  head/sys/compat/linux/linux_ioctl.c
  head/sys/compat/linux/linux_socket.c
  head/sys/compat/linux/linux_stats.c
  head/sys/compat/svr4/svr4_fcntl.c
  head/sys/compat/svr4/svr4_filio.c
  head/sys/compat/svr4/svr4_ioctl.c
  head/sys/compat/svr4/svr4_misc.c
  head/sys/compat/svr4/svr4_stream.c
  head/sys/dev/aac/aac_linux.c
  head/sys/dev/amr/amr_linux.c
  head/sys/dev/hwpmc/hwpmc_logging.c
  head/sys/dev/ipmi/ipmi_linux.c
  head/sys/dev/iscsi/initiator/iscsi.c
  head/sys/dev/mfi/mfi_linux.c
  head/sys/dev/snp/snp.c
  head/sys/dev/tdfx/tdfx_linux.c
  head/sys/fs/coda/coda_psdev.c
  head/sys/fs/fdescfs/fdesc_vnops.c
  head/sys/fs/nfsclient/nfs_clport.c
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/fs/portalfs/portal_vfsops.c
  head/sys/fs/portalfs/portal_vnops.c
  head/sys/gnu/fs/xfs/xfs_dfrag.c
  head/sys/i386/ibcs2/ibcs2_fcntl.c
  head/sys/i386/ibcs2/ibcs2_ioctl.c
  head/sys/i386/ibcs2/ibcs2_misc.c
  head/sys/i386/linux/linux_machdep.c
  head/sys/kern/kern_descrip.c
  head/sys/kern/kern_event.c
  head/sys/kern/kern_exec.c
  head/sys/kern/sys_capability.c
  head/sys/kern/sys_generic.c
  head/sys/kern/tty.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/uipc_sem.c
  head/sys/kern/uipc_syscalls.c
  head/sys/kern/vfs_acl.c
  head/sys/kern/vfs_aio.c
  head/sys/kern/vfs_extattr.c
  head/sys/kern/vfs_lookup.c
  head/sys/kern/vfs_syscalls.c
  head/sys/netgraph/ng_socket.c
  head/sys/nfsserver/nfs_srvkrpc.c
  head/sys/security/audit/audit_arg.c
  head/sys/security/mac/mac_syscalls.c
  head/sys/sys/capability.h
  head/sys/sys/file.h
  head/sys/sys/filedesc.h
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/vm/vm_mmap.c
  head/tools/regression/security/cap_test/cap_test.c
  head/tools/regression/security/cap_test/cap_test_capabilities.c

Modified: head/sys/amd64/linux32/linux32_machdep.c
==============================================================================
--- head/sys/amd64/linux32/linux32_machdep.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/amd64/linux32/linux32_machdep.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/fcntl.h>
 #include <sys/clock.h>
@@ -566,7 +567,7 @@ linux_mmap_common(struct thread *td, l_u
 		 * protection options specified.
 		 */
 
-		if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+		if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
 			return (error);
 		if (fp->f_type != DTYPE_VNODE) {
 			fdrop(fp, td);

Modified: head/sys/cddl/compat/opensolaris/sys/file.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/file.h	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/cddl/compat/opensolaris/sys/file.h	Thu Aug 11 12:30:23 2011	(r224778)
@@ -36,12 +36,18 @@
 #ifdef _KERNEL
 typedef	struct file	file_t;
 
+#include <sys/capability.h>
+
 static __inline file_t *
 getf(int fd)
 {
 	struct file *fp;
 
-	if (fget(curthread, fd, &fp) == 0)
+	/*
+	 * We wouldn't need all of these rights on every invocation
+	 * if we had more information about intent.
+	 */
+	if (fget(curthread, fd, CAP_READ | CAP_WRITE | CAP_SEEK, &fp) == 0)
 		return (fp);
 	return (NULL);
 }
@@ -51,7 +57,8 @@ releasef(int fd)
 {
 	struct file *fp;
 
-	if (fget(curthread, fd, &fp) == 0) {
+	/* No CAP_ rights required, as we're only releasing. */
+	if (fget(curthread, fd, 0, &fp) == 0) {
 		fdrop(fp, curthread);
 		fdrop(fp, curthread);
 	}

Modified: head/sys/compat/freebsd32/freebsd32_ioctl.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_ioctl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/freebsd32/freebsd32_ioctl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_compat.h"
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/cdio.h>
 #include <sys/fcntl.h>
 #include <sys/filio.h>
@@ -354,7 +355,7 @@ freebsd32_ioctl(struct thread *td, struc
 	struct file *fp;
 	int error;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0)
+	if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
 		fdrop(fp, td);

Modified: head/sys/compat/linux/linux_file.c
==============================================================================
--- head/sys/compat/linux/linux_file.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/linux/linux_file.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
@@ -141,7 +142,7 @@ linux_common_open(struct thread *td, int
 	     * having the same filedesc could use that fd without
 	     * checking below.
 	     */
-	    error = fget(td, fd, &fp);
+	    error = fget(td, fd, CAP_IOCTL, &fp);
 	    if (!error) {
 		    sx_slock(&proctree_lock);
 		    PROC_LOCK(p);
@@ -345,7 +346,7 @@ getdents_common(struct thread *td, struc
 	} else
 		justone = 0;
 
-	if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
+	if ((error = getvnode(td->td_proc->p_fd, args->fd, CAP_READ, &fp)) != 0)
 		return (error);
 
 	if ((fp->f_flag & FREAD) == 0) {
@@ -1041,7 +1042,7 @@ linux_pread(td, uap)
 
 	if (error == 0) {
    	   	/* This seems to violate POSIX but linux does it */
-   	   	if ((error = fgetvp(td, uap->fd, &vp)) != 0)
+		if ((error = fgetvp(td, uap->fd, CAP_READ, &vp)) != 0)
    		   	return (error);
 		if (vp->v_type == VDIR) {
    		   	vrele(vp);
@@ -1390,7 +1391,7 @@ fcntl_common(struct thread *td, struct l
 		 * significant effect for pipes (SIGIO is not delivered for
 		 * pipes under Linux-2.2.35 at least).
 		 */
-		error = fget(td, args->fd, &fp);
+		error = fget(td, args->fd, CAP_FCNTL, &fp);
 		if (error)
 			return (error);
 		if (fp->f_type == DTYPE_PIPE) {

Modified: head/sys/compat/linux/linux_ioctl.c
==============================================================================
--- head/sys/compat/linux/linux_ioctl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/linux/linux_ioctl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/capability.h>
 #include <sys/cdio.h>
 #include <sys/dvdio.h>
 #include <sys/conf.h>
@@ -193,7 +194,7 @@ linux_ioctl_hdio(struct thread *td, stru
 	u_int sectorsize, fwcylinders, fwheads, fwsectors;
 	off_t mediasize, bytespercyl;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	switch (args->cmd & 0xffff) {
 	case LINUX_HDIO_GET_GEO:
@@ -274,7 +275,7 @@ linux_ioctl_disk(struct thread *td, stru
 	u_int sectorsize;
 	off_t mediasize;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	switch (args->cmd & 0xffff) {
 	case LINUX_BLKGETSIZE:
@@ -700,7 +701,7 @@ linux_ioctl_termio(struct thread *td, st
 	struct file *fp;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 
 	switch (args->cmd & 0xffff) {
@@ -1440,7 +1441,7 @@ linux_ioctl_cdrom(struct thread *td, str
 	struct file *fp;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	switch (args->cmd & 0xffff) {
 
@@ -1965,7 +1966,7 @@ linux_ioctl_console(struct thread *td, s
 	struct file *fp;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	switch (args->cmd & 0xffff) {
 
@@ -2356,7 +2357,7 @@ linux_ioctl_socket(struct thread *td, st
 	ifp = NULL;
 	error = 0;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	type = fp->f_type;
 	fdrop(fp, td);
@@ -2582,7 +2583,7 @@ linux_ioctl_private(struct thread *td, s
 	struct file *fp;
 	int error, type;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	type = fp->f_type;
 	fdrop(fp, td);
@@ -2608,7 +2609,7 @@ linux_ioctl_sg(struct thread *td, struct
 	u_long cmd;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0) {
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) {
 		printf("sg_linux_ioctl: fget returned %d\n", error);
 		return (error);
 	}
@@ -2843,7 +2844,7 @@ linux_ioctl_v4l(struct thread *td, struc
 	case LINUX_VIDIOCSCHAN:		args->cmd = VIDIOCSCHAN; break;
 
 	case LINUX_VIDIOCGTUNER:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
 		if (error) {
@@ -2861,7 +2862,7 @@ linux_ioctl_v4l(struct thread *td, struc
 		return (error);
 
 	case LINUX_VIDIOCSTUNER:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
 		if (error) {
@@ -2878,7 +2879,7 @@ linux_ioctl_v4l(struct thread *td, struc
 	case LINUX_VIDIOCCAPTURE:	args->cmd = VIDIOCCAPTURE; break;
 
 	case LINUX_VIDIOCGWIN:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
 		if (!error) {
@@ -2890,7 +2891,7 @@ linux_ioctl_v4l(struct thread *td, struc
 		return (error);
 
 	case LINUX_VIDIOCSWIN:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
 		if (error) {
@@ -2913,7 +2914,7 @@ linux_ioctl_v4l(struct thread *td, struc
 		return (error);
 
 	case LINUX_VIDIOCGFBUF:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
 		if (!error) {
@@ -2925,7 +2926,7 @@ linux_ioctl_v4l(struct thread *td, struc
 		return (error);
 
 	case LINUX_VIDIOCSFBUF:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
 		if (error) {
@@ -2953,7 +2954,7 @@ linux_ioctl_v4l(struct thread *td, struc
 	case LINUX_VIDIOCGPLAYINFO:	args->cmd = VIDIOCGPLAYINFO; break;
 
 	case LINUX_VIDIOCSMICROCODE:
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
 		if (error) {
@@ -3197,7 +3198,7 @@ linux_ioctl_v4l2(struct thread *td, stru
 		error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
 		if (error)
 			return (error);
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
 			error = EINVAL;
@@ -3220,7 +3221,7 @@ linux_ioctl_v4l2(struct thread *td, stru
 		if (error)
 			return (error);
 		linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
 		    td->td_ucred, td);
@@ -3242,7 +3243,7 @@ linux_ioctl_v4l2(struct thread *td, stru
 				sizeof(struct l_v4l2_input));
 		if (error != 0)
 			return (error);
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
 		    td->td_ucred, td);
@@ -3261,7 +3262,7 @@ linux_ioctl_v4l2(struct thread *td, stru
 		error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
 		if (error)
 			return (error);
-		if ((error = fget(td, args->fd, &fp)) != 0)
+		if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 			return (error);
 		linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
 		if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
@@ -3431,7 +3432,7 @@ linux_ioctl(struct thread *td, struct li
 		    (unsigned long)args->cmd);
 #endif
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
 		fdrop(fp, td);

Modified: head/sys/compat/linux/linux_socket.c
==============================================================================
--- head/sys/compat/linux/linux_socket.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/linux/linux_socket.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/systm.h>
 #include <sys/sysproto.h>
+#include <sys/capability.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/limits.h>
@@ -743,7 +744,7 @@ linux_connect(struct thread *td, struct 
 	 * socket and use the file descriptor reference instead of
 	 * creating a new one.
 	 */
-	error = fgetsock(td, args->s, &so, &fflag);
+	error = fgetsock(td, args->s, CAP_CONNECT, &so, &fflag);
 	if (error == 0) {
 		error = EISCONN;
 		if (fflag & FNONBLOCK) {

Modified: head/sys/compat/linux/linux_stats.c
==============================================================================
--- head/sys/compat/linux/linux_stats.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/linux/linux_stats.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -141,8 +141,11 @@ translate_fd_major_minor(struct thread *
 	struct vnode *vp;
 	int major, minor;
 
+	/*
+	 * No capability rights required here.
+	 */
 	if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
-	    fget(td, fd, &fp) != 0)
+	    fget(td, fd, 0, &fp) != 0)
 		return;
 	vp = fp->f_vnode;
 	if (vp != NULL && vp->v_rdev != NULL &&

Modified: head/sys/compat/svr4/svr4_fcntl.c
==============================================================================
--- head/sys/compat/svr4/svr4_fcntl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/svr4/svr4_fcntl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -33,6 +33,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/systm.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
@@ -261,7 +262,17 @@ fd_revoke(td, fd)
 	int error, *retval;
 
 	retval = td->td_retval;
-	if ((error = fgetvp(td, fd, &vp)) != 0)
+	/*
+	 * If we ever want to support Capsicum on SVR4 processes (unlikely)
+	 * or FreeBSD grows a native frevoke() (more likely), we will need a
+	 * CAP_REVOKE here.
+	 *
+	 * In the meantime, use CAP_MASK_VALID: if a SVR4 process wants to
+	 * do an frevoke(), it needs to do it on either a regular file
+	 * descriptor or a fully-privileged capability (which is effectively
+	 * the same as a non-capability-restricted file descriptor).
+	 */
+	if ((error = fgetvp(td, fd, CAP_MASK_VALID, &vp)) != 0)
 		return (error);
 
 	if (vp->v_type != VCHR && vp->v_type != VBLK) {
@@ -313,7 +324,7 @@ fd_truncate(td, fd, flp)
 	/*
 	 * We only support truncating the file.
 	 */
-	if ((error = fget(td, fd, &fp)) != 0)
+	if ((error = fget(td, fd, CAP_FTRUNCATE, &fp)) != 0)
 		return (error);
 
 	vp = fp->f_vnode;
@@ -392,7 +403,7 @@ svr4_sys_open(td, uap)
 #if defined(NOTYET)
 		struct file	*fp;
 
-		error = fget(td, retval, &fp);
+		error = fget(td, retval, CAP_IOCTL, &fp);
 		PROC_UNLOCK(p);
 		/*
 		 * we may have lost a race the above open() and

Modified: head/sys/compat/svr4/svr4_filio.c
==============================================================================
--- head/sys/compat/svr4/svr4_filio.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/svr4/svr4_filio.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/filio.h>
 #include <sys/lock.h>
@@ -113,7 +114,7 @@ svr4_sys_read(td, uap)
      ra.buf = uap->buf;
      ra.nbyte = uap->nbyte;
 
-     if (fget(td, uap->fd, &fp) != 0) {
+     if (fget(td, uap->fd, CAP_READ, &fp) != 0) {
        DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
        return EBADF;
      }

Modified: head/sys/compat/svr4/svr4_ioctl.c
==============================================================================
--- head/sys/compat/svr4/svr4_ioctl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/svr4/svr4_ioctl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/proc.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/fcntl.h>
@@ -102,7 +103,7 @@ svr4_sys_ioctl(td, uap)
 	retval = td->td_retval;
 	cmd = uap->com;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0)
+	if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 
 	if ((fp->f_flag & (FREAD | FWRITE)) == 0) {

Modified: head/sys/compat/svr4/svr4_misc.c
==============================================================================
--- head/sys/compat/svr4/svr4_misc.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/svr4/svr4_misc.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
 #include <sys/filedesc.h>
@@ -246,7 +247,8 @@ svr4_sys_getdents64(td, uap)
 
 	DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
 		uap->fd, uap->nbytes));
-	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
+	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+	    CAP_READ | CAP_SEEK, &fp)) != 0) {
 		return (error);
 	}
 
@@ -427,7 +429,8 @@ svr4_sys_getdents(td, uap)
 	if (uap->nbytes < 0)
 		return (EINVAL);
 
-	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+	    CAP_READ | CAP_SEEK, &fp)) != 0)
 		return (error);
 
 	if ((fp->f_flag & FREAD) == 0) {
@@ -615,7 +618,8 @@ svr4_sys_fchroot(td, uap)
 
 	if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
 		return error;
-	if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
+	/* XXX: we have the chroot priv... what cap might we need? all? */
+	if ((error = getvnode(fdp, uap->fd, 0, &fp)) != 0)
 		return error;
 	vp = fp->f_vnode;
 	VREF(vp);

Modified: head/sys/compat/svr4/svr4_stream.c
==============================================================================
--- head/sys/compat/svr4/svr4_stream.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/compat/svr4/svr4_stream.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/fcntl.h>
 #include <sys/filedesc.h>
 #include <sys/filio.h>
@@ -1448,7 +1449,7 @@ svr4_sys_putmsg(td, uap)
 	struct file     *fp;
 	int error;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0) {
+	if ((error = fget(td, uap->fd, CAP_WRITE, &fp)) != 0) {
 #ifdef DEBUG_SVR4
 	        uprintf("putmsg: bad fp\n");
 #endif
@@ -1620,7 +1621,7 @@ svr4_sys_getmsg(td, uap)
 	struct file     *fp;
 	int error;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0) {
+	if ((error = fget(td, uap->fd, CAP_READ, &fp)) != 0) {
 #ifdef DEBUG_SVR4
 	        uprintf("getmsg: bad fp\n");
 #endif

Modified: head/sys/dev/aac/aac_linux.c
==============================================================================
--- head/sys/dev/aac/aac_linux.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/aac/aac_linux.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -78,7 +79,7 @@ aac_linux_ioctl(struct thread *td, struc
 	u_long cmd;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	cmd = args->cmd;
 

Modified: head/sys/dev/amr/amr_linux.c
==============================================================================
--- head/sys/dev/amr/amr_linux.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/amr/amr_linux.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -74,7 +75,7 @@ amr_linux_ioctl(struct thread *p, struct
 	struct file *fp;
 	int error;
 
-	if ((error = fget(p, args->fd, &fp)) != 0)
+	if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p);
 	fdrop(fp, p);

Modified: head/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_logging.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/hwpmc/hwpmc_logging.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -37,6 +37,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
@@ -589,7 +590,7 @@ pmclog_configure_log(struct pmc_mdep *md
 		po->po_file));
 
 	/* get a reference to the file state */
-	error = fget_write(curthread, logfd, &po->po_file);
+	error = fget_write(curthread, logfd, CAP_WRITE, &po->po_file);
 	if (error)
 		goto error;
 

Modified: head/sys/dev/ipmi/ipmi_linux.c
==============================================================================
--- head/sys/dev/ipmi/ipmi_linux.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/ipmi/ipmi_linux.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -92,7 +93,7 @@ ipmi_linux_ioctl(struct thread *td, stru
 	u_long cmd;
 	int error;
 
-	if ((error = fget(td, args->fd, &fp)) != 0)
+	if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	cmd = args->cmd;
 

Modified: head/sys/dev/iscsi/initiator/iscsi.c
==============================================================================
--- head/sys/dev/iscsi/initiator/iscsi.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/iscsi/initiator/iscsi.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_iscsi_initiator.h"
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/conf.h>
@@ -387,11 +388,11 @@ i_setsoc(isc_session_t *sp, int fd, stru
      if(sp->soc != NULL)
 	  isc_stop_receiver(sp);
 
-     error = fget(td, fd, &sp->fp);
+     error = fget(td, fd, CAP_SOCK_ALL, &sp->fp);
      if(error)
 	  return error;
 
-     if((error = fgetsock(td, fd, &sp->soc, 0)) == 0) {
+     if((error = fgetsock(td, fd, CAP_SOCK_ALL, &sp->soc, 0)) == 0) {
 	  sp->td = td;
 	  isc_start_receiver(sp);
      }

Modified: head/sys/dev/mfi/mfi_linux.c
==============================================================================
--- head/sys/dev/mfi/mfi_linux.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/mfi/mfi_linux.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -95,7 +96,7 @@ mfi_linux_ioctl(struct thread *p, struct
 		break;
 	}
 
-	if ((error = fget(p, args->fd, &fp)) != 0)
+	if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
 		return (error);
 	error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p);
 	fdrop(fp, p);

Modified: head/sys/dev/snp/snp.c
==============================================================================
--- head/sys/dev/snp/snp.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/snp/snp.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -252,6 +252,9 @@ snp_ioctl(struct cdev *dev, u_long cmd, 
 			SNP_UNLOCK();
 			return (EBUSY);
 		}
+		/*
+		 * XXXRW / XXXJA: no capability check here.
+		 */
 		error = ttyhook_register(&ss->snp_tty, td->td_proc,
 		    *(int *)data, &snp_hook, ss);
 		SNP_UNLOCK();

Modified: head/sys/dev/tdfx/tdfx_linux.c
==============================================================================
--- head/sys/dev/tdfx/tdfx_linux.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/dev/tdfx/tdfx_linux.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -28,6 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -53,7 +54,7 @@ linux_ioctl_tdfx(struct thread *td, stru
 
    struct file *fp;
 
-   if ((error = fget(td, args->fd, &fp)) != 0)
+   if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
 	   return (error);
    /* We simply copy the data and send it right to ioctl */
    copyin((caddr_t)args->arg, &d_pio, sizeof(d_pio));

Modified: head/sys/fs/coda/coda_psdev.c
==============================================================================
--- head/sys/fs/coda/coda_psdev.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/coda/coda_psdev.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/ioccom.h>
 #include <sys/kernel.h>
@@ -371,7 +372,7 @@ vc_write(struct cdev *dev, struct uio *u
 		struct vnode *vp = NULL;
 
 		if (tmp->oh.result == 0) {
-			error = getvnode(uiop->uio_td->td_proc->p_fd,
+			error = getvnode(uiop->uio_td->td_proc->p_fd, CAP_WRITE,
 			    tmp->fd, &fp);
 			if (!error) {
 				/*

Modified: head/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- head/sys/fs/fdescfs/fdesc_vnops.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/fdescfs/fdesc_vnops.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -40,6 +40,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/conf.h>
 #include <sys/dirent.h>
 #include <sys/filedesc.h>
@@ -305,7 +306,10 @@ fdesc_lookup(ap)
 		fd = fd1;
 	}
 
-	if ((error = fget(td, fd, &fp)) != 0)
+	/*
+	 * No rights to check since 'fp' isn't actually used.
+	 */
+	if ((error = fget(td, fd, 0, &fp)) != 0)
 		goto bad;
 
 	/* Check if we're looking up ourselves. */
@@ -455,7 +459,7 @@ fdesc_setattr(ap)
 	/*
 	 * Allow setattr where there is an underlying vnode.
 	 */
-	error = getvnode(td->td_proc->p_fd, fd, &fp);
+	error = getvnode(td->td_proc->p_fd, fd, CAP_EXTATTR_SET, &fp);
 	if (error) {
 		/*
 		 * getvnode() returns EINVAL if the file descriptor is not

Modified: head/sys/fs/nfsclient/nfs_clport.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clport.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/nfsclient/nfs_clport.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
 
 #include "opt_kdtrace.h"
 
+#include <sys/capability.h>
+
 /*
  * generally, I don't like #includes inside .h files, but it seems to
  * be the easiest way to handle the port.
@@ -1231,7 +1233,13 @@ nfssvc_nfscl(struct thread *td, struct n
 		error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg));
 		if (error)
 			return (error);
-		if ((error = fget(td, nfscbdarg.sock, &fp)) != 0) {
+		/*
+		 * Since we don't know what rights might be required,
+		 * pretend that we need them all. It is better to be too
+		 * careful than too reckless.
+		 */
+		if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_ALL, &fp))
+		    != 0) {
 			return (error);
 		}
 		if (fp->f_type != DTYPE_SOCKET) {

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -34,6 +34,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/capability.h>
+
 /*
  * Functions that perform the vfs operations required by the routines in
  * nfsd_serv.c. It is hoped that this change will make the server more
@@ -3027,8 +3029,14 @@ nfssvc_nfsd(struct thread *td, struct nf
 		error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg));
 		if (error)
 			goto out;
-		if ((error = fget(td, sockarg.sock, &fp)) != 0)
+		/*
+		 * Since we don't know what rights might be required,
+		 * pretend that we need them all. It is better to be too
+		 * careful than too reckless.
+		 */
+		if ((error = fget(td, sockarg.sock, CAP_SOCK_ALL, &fp)) != 0)
 			goto out;
+			return (error);
 		if (fp->f_type != DTYPE_SOCKET) {
 			fdrop(fp, td);
 			error = EPERM;

Modified: head/sys/fs/portalfs/portal_vfsops.c
==============================================================================
--- head/sys/fs/portalfs/portal_vfsops.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/portalfs/portal_vfsops.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -40,6 +40,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/domain.h>
 #include <sys/filedesc.h>
 #include <sys/kernel.h>
@@ -112,7 +113,12 @@ portal_mount(struct mount *mp)
 	if (error)
 		return (error);
 
-	if ((error = fget(td, v, &fp)) != 0)
+	/*
+	 * Capsicum is not incompatible with portalfs, but we don't really
+	 * know what rights are required. In the spirit of "better safe than
+	 * sorry", pretend that all rights are required for now.
+	 */
+	if ((error = fget(td, v, CAP_MASK_VALID, &fp)) != 0)
 		return (error);
         if (fp->f_type != DTYPE_SOCKET) {
 		fdrop(fp, td);

Modified: head/sys/fs/portalfs/portal_vnops.c
==============================================================================
--- head/sys/fs/portalfs/portal_vnops.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/fs/portalfs/portal_vnops.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -38,7 +38,10 @@
  * Portal Filesystem
  */
 
+#include "opt_capsicum.h"
+
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/kernel.h>
@@ -232,6 +235,15 @@ portal_open(ap)
 	struct file *fp;
 	struct portal_cred pcred;
 
+#ifdef CAPABILITY_MODE
+	/*
+	 * This may require access to a global namespace (e.g. an IP address);
+	 * disallow it entirely, as we do open(2).
+	 */
+	if (IN_CAPABILITY_MODE(td))
+		return (ECAPMODE);
+#endif
+
 	/*
 	 * Nothing to do when opening the root node.
 	 */
@@ -414,7 +426,7 @@ portal_open(ap)
 	 * Check that the mode the file is being opened for is a subset
 	 * of the mode of the existing descriptor.
 	 */
-	if ((error = fget(td, fd, &fp)) != 0)
+	if ((error = fget(td, fd, 0, &fp)) != 0)
 		goto bad;
 	if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
 		fdrop(fp, td);

Modified: head/sys/gnu/fs/xfs/xfs_dfrag.c
==============================================================================
--- head/sys/gnu/fs/xfs/xfs_dfrag.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/gnu/fs/xfs/xfs_dfrag.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -46,6 +46,7 @@
 #include "xfs_mac.h"
 #include "xfs_rw.h"
 
+#include <sys/capability.h>
 #include <sys/file.h>
 
 /*
@@ -79,7 +80,8 @@ xfs_swapext(
 	}
 
 	/* Pull information for the target fd */
-	if (fgetvp(td, (int)sxp->sx_fdtarget, &bvp) != 0) {
+	if (fgetvp(td, (int)sxp->sx_fdtarget, CAP_READ | CAP_WRITE, &bvp)
+	    != 0) {
 		error = XFS_ERROR(EINVAL);
 		goto error0;
 	}
@@ -91,7 +93,7 @@ xfs_swapext(
 		goto error0;
 	}
 
-	if (fgetvp(td, (int)sxp->sx_fdtmp, &btvp) != 0) {
+	if (fgetvp(td, (int)sxp->sx_fdtmp, CAP_READ | CAP_WRITE, &btvp) != 0) {
 		error = XFS_ERROR(EINVAL);
 		goto error0;
 	}

Modified: head/sys/i386/ibcs2/ibcs2_fcntl.c
==============================================================================
--- head/sys/i386/ibcs2/ibcs2_fcntl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/i386/ibcs2/ibcs2_fcntl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
@@ -203,7 +204,7 @@ ibcs2_open(td, uap)
 		struct file *fp;
 		int error;
 
-		error = fget(td, td->td_retval[0], &fp);
+		error = fget(td, td->td_retval[0], CAP_IOCTL, &fp);
 		PROC_UNLOCK(p);
 		if (error)
 			return (EBADF);

Modified: head/sys/i386/ibcs2/ibcs2_ioctl.c
==============================================================================
--- head/sys/i386/ibcs2/ibcs2_ioctl.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/i386/ibcs2/ibcs2_ioctl.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/consio.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
@@ -333,7 +334,7 @@ ibcs2_ioctl(td, uap)
 	struct file *fp;
 	int error;
 
-	if ((error = fget(td, uap->fd, &fp)) != 0) {
+	if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) {
 		DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
 			 uap->fd));
 		return EBADF;

Modified: head/sys/i386/ibcs2/ibcs2_misc.c
==============================================================================
--- head/sys/i386/ibcs2/ibcs2_misc.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/i386/ibcs2/ibcs2_misc.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
  */
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
 #include <sys/filedesc.h>
@@ -336,7 +337,8 @@ ibcs2_getdents(td, uap)
 #define	BSD_DIRENT(cp)		((struct dirent *)(cp))
 #define	IBCS2_RECLEN(reclen)	(reclen + sizeof(u_short))
 
-	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+	    CAP_READ | CAP_SEEK, &fp)) != 0)
 		return (error);
 	if ((fp->f_flag & FREAD) == 0) {
 		fdrop(fp, td);
@@ -492,7 +494,8 @@ ibcs2_read(td, uap)
 	u_long *cookies = NULL, *cookiep;
 	int ncookies;
 
-	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
+	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+	    CAP_READ | CAP_SEEK, &fp)) != 0) {
 		if (error == EINVAL)
 			return read(td, (struct read_args *)uap);
 		else

Modified: head/sys/i386/linux/linux_machdep.c
==============================================================================
--- head/sys/i386/linux/linux_machdep.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/i386/linux/linux_machdep.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/fcntl.h>
 #include <sys/imgact.h>
@@ -467,9 +468,12 @@ linux_mmap_common(struct thread *td, l_u
 		 * The file descriptor fildes is opened with
 		 * read permission, regardless of the
 		 * protection options specified.
+		 *
+		 * Checking just CAP_MMAP is fine here, since the real work
+		 * is done in the FreeBSD mmap().
 		 */
 
-		if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+		if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
 			return (error);
 		if (fp->f_type != DTYPE_VNODE) {
 			fdrop(fp, td);

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Thu Aug 11 11:30:21 2011	(r224777)
+++ head/sys/kern/kern_descrip.c	Thu Aug 11 12:30:23 2011	(r224778)
@@ -431,6 +431,26 @@ fdtofp(int fd, struct filedesc *fdp)
 	return (fp);
 }
 
+static inline int
+fdunwrap(int fd, cap_rights_t rights, struct filedesc *fdp, struct file **fpp)
+{
+
+	*fpp = fdtofp(fd, fdp);
+	if (*fpp == NULL)
+		return (EBADF);
+
+#ifdef CAPABILITIES
+	if ((*fpp)->f_type == DTYPE_CAPABILITY) {
+		int err = cap_funwrap(*fpp, rights, fpp);
+		if (err != 0) {
+			*fpp = NULL;
+			return (err);
+		}
+	}
+#endif /* CAPABILITIES */
+	return (0);
+}
+
 int
 kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
 {
@@ -489,9 +509,9 @@ kern_fcntl(struct thread *td, int fd, in
 
 	case F_GETFL:
 		FILEDESC_SLOCK(fdp);
-		if ((fp = fdtofp(fd, fdp)) == NULL) {
+		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+		if (error != 0) {
 			FILEDESC_SUNLOCK(fdp);
-			error = EBADF;
 			break;
 		}
 		td->td_retval[0] = OFLAGS(fp->f_flag);
@@ -500,9 +520,9 @@ kern_fcntl(struct thread *td, int fd, in
 
 	case F_SETFL:
 		FILEDESC_SLOCK(fdp);
-		if ((fp = fdtofp(fd, fdp)) == NULL) {
+		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+		if (error != 0) {
 			FILEDESC_SUNLOCK(fdp);
-			error = EBADF;
 			break;
 		}
 		fhold(fp);
@@ -532,9 +552,9 @@ kern_fcntl(struct thread *td, int fd, in
 
 	case F_GETOWN:
 		FILEDESC_SLOCK(fdp);
-		if ((fp = fdtofp(fd, fdp)) == NULL) {
+		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+		if (error != 0) {
 			FILEDESC_SUNLOCK(fdp);
-			error = EBADF;
 			break;
 		}
 		fhold(fp);
@@ -547,9 +567,9 @@ kern_fcntl(struct thread *td, int fd, in
 
 	case F_SETOWN:
 		FILEDESC_SLOCK(fdp);
-		if ((fp = fdtofp(fd, fdp)) == NULL) {
+		error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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