PERFORCE change 133771 for review
Robert Watson
rwatson at FreeBSD.org
Mon Jan 21 03:02:25 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=133771
Change 133771 by rwatson at rwatson_freebsd_capabilities on 2008/01/21 11:02:01
Use panic() rather than KASSERT() to handle failure to allocate a
zone for capabilities -- we want to fail cleanly even without
INVARIANTS.
Add cap_check() utility routine to test rights on a capability, and
use in various fo_* methods.
Add cap_fget(), which given a file descriptor that may be a
capability, tests the rights against the capability (if any) and
returns the actual object file descriptor to operate on. This is
just a first hack and it will almost certainly change.
Affected files ...
.. //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_capability.c#2 edit
.. //depot/projects/trustedbsd/capabilities/src/sys/sys/capability.h#3 edit
Differences ...
==== //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_capability.c#2 (text+ko) ====
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$P4: //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_capability.c#1 $");
+__FBSDID("$P4: //depot/projects/trustedbsd/capabilities/src/sys/kern/sys_capability.c#2 $");
#include <sys/param.h>
#include <sys/capability.h>
@@ -110,14 +110,55 @@
capability_init(void *dummy __unused)
{
- capability_zone = uma_zcreate("pipe", sizeof(struct capability),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- KASSERT(capability_zone != NULL,
- ("capability_zone not initialized"));
+ capability_zone = uma_zcreate("capability",
+ sizeof(struct capability), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+ 0);
+ if (capability_zone == NULL)
+ panic("capability_init: capability_zone not initialized");
}
SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, capability_init, NULL);
/*
+ * 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 (EACCES);
+ 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.
+ *
+ * XXXRW: This will almost certainly change.
+ */
+int
+cap_fget(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_file;
+ return (0);
+}
+
+/*
* Create a new capability reference to either an existing file object or an
* an existing capability.
*/
@@ -140,6 +181,9 @@
* If a new capability is being derived from an existing capability,
* then the new capability rights must be a subset of the existing
* rights.
+ *
+ * XXXRW: Should we have a priv_check() here that can override this
+ * policy?
*/
if (fp->f_type == DTYPE_CAPABILITY) {
c_old = fp->f_data;
@@ -210,15 +254,15 @@
int flags, struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_read: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_READ))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_read(fp_object, uio, active_cred, flags, td));
+ error = cap_check(c, CAP_READ);
+ if (error)
+ return (error);
+ return (fo_read(c->cap_file, uio, active_cred, flags, td));
}
static int
@@ -226,15 +270,15 @@
int flags, struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_write: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_WRITE))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_write(fp_object, uio, active_cred, flags, td));
+ error = cap_check(c, CAP_WRITE);
+ if (error)
+ return (error);
+ return (fo_write(c->cap_file, uio, active_cred, flags, td));
}
static int
@@ -242,15 +286,15 @@
struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_truncate: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_FTRUNCATE))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_truncate(fp_object, length, active_cred, td));
+ error = cap_check(c, CAP_FTRUNCATE);
+ if (error)
+ return (error);
+ return (fo_truncate(c->cap_file, length, active_cred, td));
}
static int
@@ -258,15 +302,15 @@
struct ucred *active_cred, struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_ioctl: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_IOCTL))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_ioctl(fp_object, com, data, active_cred, td));
+ error = cap_check(c, CAP_IOCTL);
+ if (error)
+ return (error);
+ return (fo_ioctl(c->cap_file, com, data, active_cred, td));
}
static int
@@ -274,30 +318,30 @@
struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_poll: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_EVENT))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_poll(fp_object, events, active_cred, td));
+ error = cap_check(c, CAP_EVENT);
+ if (error)
+ return (error);
+ return (fo_poll(c->cap_file, events, active_cred, td));
}
static int
capability_kqfilter(struct file *fp, struct knote *kn)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_kqfilter: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_EVENT))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_kqfilter(fp_object, kn));
+ error = cap_check(c, CAP_EVENT);
+ if (error)
+ return (error);
+ return (fo_kqfilter(c->cap_file, kn));
}
static int
@@ -305,15 +349,15 @@
struct thread *td)
{
struct capability *c;
- struct file *fp_object;
+ int error;
KASSERT(fp->f_type == DTYPE_CAPABILITY,
("capability_stat: !capability"));
c = fp->f_data;
- if (!(c->cap_rights & CAP_FSTAT))
- return (EACCES);
- fp_object = c->cap_file;
- return (fo_stat(fp_object, sb, active_cred, td));
+ error = cap_check(c, CAP_FSTAT);
+ if (error)
+ return (error);
+ return (fo_stat(c->cap_file, sb, active_cred, td));
}
static int
==== //depot/projects/trustedbsd/capabilities/src/sys/sys/capability.h#3 (text+ko) ====
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $P4: //depot/projects/trustedbsd/capabilities/src/sys/sys/capability.h#2 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/sys/sys/capability.h#3 $
*/
/*
@@ -105,6 +105,9 @@
*/
#ifdef _KERNEL
+struct file;
+int cap_fget(struct file *fp_cap, cap_rights_t rights,
+ struct file **fpp);
#else /* !_KERNEL */
More information about the p4-projects
mailing list