PERFORCE change 133786 for review
Robert Watson
rwatson at FreeBSD.org
Mon Jan 21 07:36:12 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=133786
Change 133786 by rwatson at 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_
More information about the p4-projects
mailing list