summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_capability.c
diff options
context:
space:
mode:
authorjonathan <jonathan@FreeBSD.org>2011-07-04 14:40:32 +0000
committerjonathan <jonathan@FreeBSD.org>2011-07-04 14:40:32 +0000
commitbf3c575ea10a1dcfc91fd0a12ee780ae2fecb45b (patch)
tree29a4035b895c02fe764685c2ad0d0b095e7d06d6 /sys/kern/sys_capability.c
parentab5a5d466b2082866369977570d27eae453daffd (diff)
downloadFreeBSD-src-bf3c575ea10a1dcfc91fd0a12ee780ae2fecb45b.zip
FreeBSD-src-bf3c575ea10a1dcfc91fd0a12ee780ae2fecb45b.tar.gz
Add kernel functions to unwrap capabilities.
cap_funwrap() and cap_funwrap_mmap() unwrap capabilities, exposing the underlying object. Attempting to unwrap a capability with an inadequate rights mask (e.g. calling cap_funwrap(fp, CAP_WRITE | CAP_MMAP, &result) on a capability whose rights mask is CAP_READ | CAP_MMAP) will result in ENOTCAPABLE. Unwrapping a non-capability is effectively a no-op. These functions will be used by Capsicum-aware versions of _fget(), etc. Approved by: mentor (rwatson), re (Capsicum blanket) Sponsored by: Google Inc
Diffstat (limited to 'sys/kern/sys_capability.c')
-rw-r--r--sys/kern/sys_capability.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index a19e881..8216bea 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -116,3 +116,125 @@ cap_getmode(struct thread *td, struct cap_getmode_args *uap)
}
#endif /* CAPABILITY_MODE */
+
+#ifdef CAPABILITIES
+
+/*
+ * struct capability describes a capability, and is hung off of its struct
+ * file f_data field. cap_file and cap_rightss are static once hooked up, as
+ * neither the object it references nor the rights it encapsulates are
+ * permitted to change. cap_filelist may change when other capabilites are
+ * added or removed from the same file, and is currently protected by the
+ * pool mutex for the object file descriptor.
+ */
+struct capability {
+ struct file *cap_object; /* Underlying object's file. */
+ struct file *cap_file; /* Back-pointer to cap's file. */
+ cap_rights_t cap_rights; /* Mask of rights on object. */
+ LIST_ENTRY(capability) cap_filelist; /* Object's cap list. */
+};
+
+/*
+ * Test whether a capability grants the requested rights.
+ */
+static int
+cap_check(struct capability *c, cap_rights_t rights)
+{
+
+ if ((c->cap_rights | rights) != c->cap_rights)
+ return (ENOTCAPABLE);
+ return (0);
+}
+
+/*
+ * Given a file descriptor, test it against a capability rights mask and then
+ * return the file descriptor on which to actually perform the requested
+ * operation. As long as the reference to fp_cap remains valid, the returned
+ * pointer in *fp will remain valid, so no extra reference management is
+ * required, and the caller should fdrop() fp_cap as normal when done with
+ * both.
+ */
+int
+cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp)
+{
+ struct capability *c;
+ int error;
+
+ if (fp_cap->f_type != DTYPE_CAPABILITY) {
+ *fpp = fp_cap;
+ return (0);
+ }
+ c = fp_cap->f_data;
+ error = cap_check(c, rights);
+ if (error)
+ return (error);
+ *fpp = c->cap_object;
+ return (0);
+}
+
+/*
+ * Slightly different routine for memory mapping file descriptors: unwrap the
+ * capability and check CAP_MMAP, but also return a bitmask representing the
+ * maximum mapping rights the capability allows on the object.
+ */
+int
+cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp,
+ struct file **fpp)
+{
+ struct capability *c;
+ u_char maxprot;
+ int error;
+
+ if (fp_cap->f_type != DTYPE_CAPABILITY) {
+ *fpp = fp_cap;
+ *maxprotp = VM_PROT_ALL;
+ return (0);
+ }
+ c = fp_cap->f_data;
+ error = cap_check(c, rights | CAP_MMAP);
+ if (error)
+ return (error);
+ *fpp = c->cap_object;
+ maxprot = 0;
+ if (c->cap_rights & CAP_READ)
+ maxprot |= VM_PROT_READ;
+ if (c->cap_rights & CAP_WRITE)
+ maxprot |= VM_PROT_WRITE;
+ if (c->cap_rights & CAP_MAPEXEC)
+ maxprot |= VM_PROT_EXECUTE;
+ *maxprotp = maxprot;
+ return (0);
+}
+
+#else /* !CAPABILITIES */
+
+/*
+ * Stub Capability functions for when options CAPABILITIES isn't compiled
+ * into the kernel.
+ */
+int
+cap_funwrap(struct file *fp_cap, cap_rights_t rights, struct file **fpp)
+{
+
+ KASSERT(fp_cap->f_type != DTYPE_CAPABILITY,
+ ("cap_funwrap: saw capability"));
+
+ *fpp = fp_cap;
+ return (0);
+}
+
+int
+cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp,
+ struct file **fpp)
+{
+
+ KASSERT(fp_cap->f_type != DTYPE_CAPABILITY,
+ ("cap_funwrap_mmap: saw capability"));
+
+ *fpp = fp_cap;
+ *maxprotp = VM_PROT_ALL;
+ return (0);
+}
+
+#endif /* CAPABILITIES */
+
OpenPOWER on IntegriCloud