From owner-p4-projects@FreeBSD.ORG Mon Jan 21 15:36:12 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 388E116A420; Mon, 21 Jan 2008 15:36:12 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 98DB116A418 for ; Mon, 21 Jan 2008 15:36:11 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 8893D13C4E7 for ; Mon, 21 Jan 2008 15:36:11 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m0LFaBss044225 for ; Mon, 21 Jan 2008 15:36:11 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m0LFaBj2044222 for perforce@freebsd.org; Mon, 21 Jan 2008 15:36:11 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Mon, 21 Jan 2008 15:36:11 GMT Message-Id: <200801211536.m0LFaBj2044222@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Cc: Subject: PERFORCE change 133786 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Jan 2008 15:36:12 -0000 http://perforce.freebsd.org/chv.cgi?CH=133786 Change 133786 by rwatson@rwatson_freebsd_capabilities on 2008/01/21 15:35:23 Move getvnode() to the top of vfs_syscalls.c, and implement a new getvnode_cap() that performs capability rights checks and de-nesting. Update various file descriptor-based system calls to work with capabilities and check capability rights. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/sys/kern/vfs_syscalls.c#2 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/sys/kern/vfs_syscalls.c#2 (text+ko) ==== @@ -37,6 +37,7 @@ #include __FBSDID("$FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.448 2008/01/13 14:44:10 attilio Exp $"); +#include "opt_capabilities.h" #include "opt_compat.h" #include "opt_mac.h" @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -102,6 +104,92 @@ #endif /* + * Convert a user file descriptor to a kernel file entry. + * A reference on the file entry is held upon returning. + */ +int +getvnode(fdp, fd, fpp) + struct filedesc *fdp; + int fd; + struct file **fpp; +{ + int error; + struct file *fp; + + fp = NULL; + if (fdp == NULL) + error = EBADF; + else { + FILEDESC_SLOCK(fdp); + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) + error = EBADF; + else if (fp->f_vnode == NULL) { + fp = NULL; + error = EINVAL; + } else { + fhold(fp); + error = 0; + } + FILEDESC_SUNLOCK(fdp); + } + *fpp = fp; + return (error); +} + +/* + * 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 +getvnode_cap(struct filedesc *fdp, int fd, cap_rights_t rights, + struct file **fpp) +{ + struct file *fp; + int error; + + fp = NULL; + if (fdp == NULL) { + *fpp = NULL; + return (EBADF); + } + FILEDESC_SLOCK(fdp); + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) { + error = EBADF; + fp = NULL; + 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); +} + +/* * Sync each mounted filesystem. */ #ifndef _SYS_SYSPROTO_H_ @@ -359,7 +447,7 @@ int error; AUDIT_ARG(fd, fd); - error = getvnode(td->td_proc->p_fd, fd, &fp); + error = getvnode_cap(td->td_proc->p_fd, fd, CAP_FSTATFS, &fp); if (error) return (error); vp = fp->f_vnode; @@ -726,7 +814,7 @@ int error; AUDIT_ARG(fd, uap->fd); - if ((error = getvnode(fdp, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(fdp, uap->fd, CAP_FCHDIR, &fp)) != 0) return (error); vp = fp->f_vnode; VREF(vp); @@ -2496,7 +2584,8 @@ AUDIT_ARG(fd, uap->fd); AUDIT_ARG(fflags, uap->flags); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, CAP_FCHFLAGS, + &fp)) != 0) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT @@ -2636,7 +2725,8 @@ AUDIT_ARG(fd, uap->fd); AUDIT_ARG(mode, uap->mode); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, CAP_FCHMOD, + &fp)) != 0) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT @@ -2793,7 +2883,8 @@ AUDIT_ARG(fd, uap->fd); AUDIT_ARG(owner, uap->uid, uap->gid); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, CAP_FCHOWN, + &fp)) != 0) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT @@ -3006,7 +3097,8 @@ AUDIT_ARG(fd, fd); if ((error = getutimes(tptr, tptrseg, ts)) != 0) return (error); - if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) + != 0) return (error); vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); #ifdef AUDIT @@ -3159,7 +3251,8 @@ int error; AUDIT_ARG(fd, uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, CAP_FSYNC, + &fp)) != 0) return (error); vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); @@ -3528,7 +3621,8 @@ /* XXX arbitrary sanity limit on `count'. */ if (uap->count > 64 * 1024) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, + CAP_GETDIRENTRIES, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -3670,7 +3764,8 @@ int error, eofflag; AUDIT_ARG(fd, uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode_cap(td->td_proc->p_fd, uap->fd, + CAP_GETDIRENTRIES, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -3836,40 +3931,6 @@ } /* - * Convert a user file descriptor to a kernel file entry. - * A reference on the file entry is held upon returning. - */ -int -getvnode(fdp, fd, fpp) - struct filedesc *fdp; - int fd; - struct file **fpp; -{ - int error; - struct file *fp; - - fp = NULL; - if (fdp == NULL) - error = EBADF; - else { - FILEDESC_SLOCK(fdp); - if ((u_int)fd >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[fd]) == NULL) - error = EBADF; - else if (fp->f_vnode == NULL) { - fp = NULL; - error = EINVAL; - } else { - fhold(fp); - error = 0; - } - FILEDESC_SUNLOCK(fdp); - } - *fpp = fp; - return (error); -} - -/* * Get an (NFS) file handle. */ #ifndef _SYS_SYSPROTO_H_