svn commit: r223785 - in head/sys: kern sys
Jonathan Anderson
jonathan at FreeBSD.org
Tue Jul 5 13:45:10 UTC 2011
Author: jonathan
Date: Tue Jul 5 13:45:10 2011
New Revision: 223785
URL: http://svn.freebsd.org/changeset/base/223785
Log:
Rework _fget to accept capability parameters.
This new version of _fget() requires new parameters:
- cap_rights_t needrights
the rights that we expect the capability's rights mask to include
(e.g. CAP_READ if we are going to read from the file)
- cap_rights_t *haverights
used to return the capability's rights mask (ignored if NULL)
- u_char *maxprotp
the maximum mmap() rights (e.g. VM_PROT_READ) that can be permitted
(only used if we are going to mmap the file; ignored if NULL)
- int fget_flags
FGET_GETCAP if we want to return the capability itself, rather than
the underlying object which it wraps
Approved by: mentor (rwatson), re (Capsicum blanket)
Sponsored by: Google Inc
Modified:
head/sys/kern/kern_descrip.c
head/sys/sys/file.h
Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c Tue Jul 5 10:37:17 2011 (r223784)
+++ head/sys/kern/kern_descrip.c Tue Jul 5 13:45:10 2011 (r223785)
@@ -37,6 +37,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_capsicum.h"
#include "opt_compat.h"
#include "opt_ddb.h"
#include "opt_ktrace.h"
@@ -44,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/domain.h>
#include <sys/fcntl.h>
@@ -91,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
#include <vm/uma.h>
+#include <vm/vm.h>
#include <ddb/ddb.h>
@@ -2259,15 +2262,27 @@ fget_unlocked(struct filedesc *fdp, int
* If the descriptor doesn't exist or doesn't match 'flags', EBADF is
* returned.
*
+ * If the FGET_GETCAP flag is set, the capability itself will be returned.
+ * Calling _fget() with FGET_GETCAP on a non-capability will return EINVAL.
+ * Otherwise, if the file is a capability, its rights will be checked against
+ * the capability rights mask, and if successful, the object will be unwrapped.
+ *
* If an error occured the non-zero error is returned and *fpp is set to
* NULL. Otherwise *fpp is held and set and zero is returned. Caller is
* responsible for fdrop().
*/
+#define FGET_GETCAP 0x00000001
static __inline int
-_fget(struct thread *td, int fd, struct file **fpp, int flags)
+_fget(struct thread *td, int fd, struct file **fpp, int flags,
+ cap_rights_t needrights, cap_rights_t *haverights, u_char *maxprotp,
+ int fget_flags)
{
struct filedesc *fdp;
struct file *fp;
+#ifdef CAPABILITIES
+ struct file *fp_fromcap;
+ int error;
+#endif
*fpp = NULL;
if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
@@ -2278,6 +2293,47 @@ _fget(struct thread *td, int fd, struct
fdrop(fp, td);
return (EBADF);
}
+
+#ifdef CAPABILITIES
+ /*
+ * If a capability has been requested, return the capability directly.
+ * Otherwise, check capability rights, extract the underlying object,
+ * and check its access flags.
+ */
+ if (fget_flags & FGET_GETCAP) {
+ if (fp->f_type != DTYPE_CAPABILITY) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ } else {
+ if (maxprotp == NULL)
+ error = cap_funwrap(fp, needrights, &fp_fromcap);
+ else
+ error = cap_funwrap_mmap(fp, needrights, maxprotp,
+ &fp_fromcap);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+
+ /*
+ * If we've unwrapped a file, drop the original capability
+ * and hold the new descriptor. fp after this point refers to
+ * the actual (unwrapped) object, not the capability.
+ */
+ if (fp != fp_fromcap) {
+ fhold(fp_fromcap);
+ fdrop(fp, td);
+ fp = fp_fromcap;
+ }
+ }
+#else /* !CAPABILITIES */
+ KASSERT(fp->f_type != DTYPE_CAPABILITY,
+ ("%s: saw capability", __func__));
+ if (maxprotp != NULL)
+ *maxprotp = VM_PROT_ALL;
+#endif /* CAPABILITIES */
+
/*
* FREAD and FWRITE failure return EBADF as per POSIX.
*
@@ -2296,23 +2352,36 @@ int
fget(struct thread *td, int fd, struct file **fpp)
{
- return(_fget(td, fd, fpp, 0));
+ return(_fget(td, fd, fpp, 0, 0, NULL, NULL, 0));
}
int
fget_read(struct thread *td, int fd, struct file **fpp)
{
- return(_fget(td, fd, fpp, FREAD));
+ return(_fget(td, fd, fpp, FREAD, 0, NULL, NULL, 0));
}
int
fget_write(struct thread *td, int fd, struct file **fpp)
{
- return(_fget(td, fd, fpp, FWRITE));
+ return(_fget(td, fd, fpp, FWRITE, 0, NULL, NULL, 0));
+}
+
+/*
+ * Unlike the other fget() calls, which will accept and check capability rights
+ * but never return capabilities, fgetcap() returns the capability but doesn't
+ * check capability rights.
+ */
+int
+fgetcap(struct thread *td, int fd, struct file **fpp)
+{
+
+ return (_fget(td, fd, fpp, 0, 0, NULL, NULL, FGET_GETCAP));
}
+
/*
* Like fget() but loads the underlying vnode, or returns an error if the
* descriptor does not represent a vnode. Note that pipes use vnodes but
@@ -2327,7 +2396,7 @@ _fgetvp(struct thread *td, int fd, struc
int error;
*vpp = NULL;
- if ((error = _fget(td, fd, &fp, flags)) != 0)
+ if ((error = _fget(td, fd, &fp, flags, 0, NULL, NULL, 0)) != 0)
return (error);
if (fp->f_vnode == NULL) {
error = EINVAL;
@@ -2383,7 +2452,7 @@ fgetsock(struct thread *td, int fd, stru
*spp = NULL;
if (fflagp != NULL)
*fflagp = 0;
- if ((error = _fget(td, fd, &fp, 0)) != 0)
+ if ((error = _fget(td, fd, &fp, 0, 0, NULL, NULL, 0)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
error = ENOTSOCK;
Modified: head/sys/sys/file.h
==============================================================================
--- head/sys/sys/file.h Tue Jul 5 10:37:17 2011 (r223784)
+++ head/sys/sys/file.h Tue Jul 5 13:45:10 2011 (r223785)
@@ -179,6 +179,7 @@ extern volatile int openfiles; /* actual
int fget(struct thread *td, int fd, struct file **fpp);
int fget_read(struct thread *td, int fd, struct file **fpp);
int fget_write(struct thread *td, int fd, struct file **fpp);
+int fgetcap(struct thread *td, int fd, struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
/*
More information about the svn-src-all
mailing list