Date: Mon, 21 Jan 2008 15:36:11 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 133786 for review Message-ID: <200801211536.m0LFaBj2044222@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <sys/cdefs.h> __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 <sys/systm.h> #include <sys/bio.h> #include <sys/buf.h> +#include <sys/capability.h> #include <sys/sysent.h> #include <sys/malloc.h> #include <sys/mount.h> @@ -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_
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801211536.m0LFaBj2044222>