svn commit: r203242 - projects/capabilities8/lib/libcapability
Robert Watson
rwatson at FreeBSD.org
Sat Jan 30 20:06:52 UTC 2010
Author: rwatson
Date: Sat Jan 30 20:06:52 2010
New Revision: 203242
URL: http://svn.freebsd.org/changeset/base/203242
Log:
Merge c173834 from the p4 TrustedBSD Capabilities branch to capabilities8:
Initial lc_fdlist work. No mmap'ing yet.
Submitted by: Jonathan Anderson <jonathan.anderson at cl.cam.ac.uk>
Added:
projects/capabilities8/lib/libcapability/libcapability_fdlist.c
Modified:
projects/capabilities8/lib/libcapability/Makefile
projects/capabilities8/lib/libcapability/libcapability.h
Modified: projects/capabilities8/lib/libcapability/Makefile
==============================================================================
--- projects/capabilities8/lib/libcapability/Makefile Sat Jan 30 20:04:59 2010 (r203241)
+++ projects/capabilities8/lib/libcapability/Makefile Sat Jan 30 20:06:52 2010 (r203242)
@@ -10,7 +10,7 @@ SRCS= \
libcapability_sandbox_io.c \
libcapability_host.c \
libcapability_host_io.c \
- libcapability_registry.c
+ libcapability_fdlist.c
INCS= libcapability.h
Modified: projects/capabilities8/lib/libcapability/libcapability.h
==============================================================================
--- projects/capabilities8/lib/libcapability/libcapability.h Sat Jan 30 20:04:59 2010 (r203241)
+++ projects/capabilities8/lib/libcapability/libcapability.h Sat Jan 30 20:06:52 2010 (r203242)
@@ -30,13 +30,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapability/libcapability.h#26 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapability/libcapability.h#27 $
*/
#ifndef _LIBCAPABILITY_H_
#define _LIBCAPABILITY_H_
#include <sys/cdefs.h>
+#include <sys/capability.h>
__BEGIN_DECLS
@@ -52,29 +53,53 @@ struct lc_library {
int lcl_fd;
};
-/*
- * A file descriptor "registry"
- */
-struct lc_fdregistry_entry;
-struct lc_fdregistry {
- struct lc_fdregistry_entry *entries; /* registry entries */
- unsigned int count; /* number of entries */
- unsigned int capacity; /* entries that we can hold */
-};
+/* A list of file descriptors, which can be passed around in shared memory */
+struct lc_fdlist;
+
+
+struct lc_fdlist* lc_fdlist_new(void);
+struct lc_fdlist* lc_fdlist_dup(struct lc_fdlist *orig);
+void lc_fdlist_free(struct lc_fdlist *l);
+
+/* Size of an FD list in bytes, including all associated string data */
+int lc_fdlist_size(struct lc_fdlist *l);
+
/*
- * Registry operations
+ * Add a file descriptor to the list.
+ *
+ * l the list to add to
+ * subsystem a software component name, e.g. "org.freebsd.rtld-elf"
+ * classname a class name, e.g. "libdir" or "library"
+ * name an instance name, e.g. "system library dir" or "libc.so.6"
+ * fd the file descriptor
*/
-struct lc_fdregistry* lc_fdregistry_new(void);
-struct lc_fdregistry* lc_fdregistry_dup(const struct lc_fdregistry *orig);
-void lc_fdregistry_free(struct lc_fdregistry *registry);
+int lc_fdlist_add(struct lc_fdlist **l,
+ const char *subsystem, const char *classname,
+ const char *name, int fd);
-int lc_fdregistry_add(const struct lc_fdregistry *reg,
- const char *id, const char *name, int fd);
+/*
+ * Like lc_fdlist_add(), but allows capability rights to be specified. The file
+ * descriptor will be wrapped in a capability with the given rights (so if the
+ * descriptor *is* a capability, its rights will be constrained according to this
+ * rights mask)
+ */
+int lc_fdlist_addcap(struct lc_fdlist **l,
+ const char *subsystem, const char *classname,
+ const char *name, int fd, cap_rights_t rights);
-int lc_fdregistry_lookup(const struct lc_fdregistry *reg,
- const char *id, char **name, int *fdp);
+/*
+ * Look up a file descriptor.
+ *
+ * Multiple entries with the same classname are allowed, so iterating through
+ * all instances of a class is done by supplying an integer 'pos' which is used
+ * internally to skip entries which have already been seen. If 'pos' is 0 or NULL,
+ * the first matching entry will be returned.
+ */
+int lc_fdlist_lookup(struct lc_fdlist *l,
+ const char *subsystem, const char *classname,
+ char **name, int *fdp, int *pos);
/*
* Capability interfaces.
Added: projects/capabilities8/lib/libcapability/libcapability_fdlist.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/capabilities8/lib/libcapability/libcapability_fdlist.c Sat Jan 30 20:06:52 2010 (r203242)
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 2009 Jonathan Anderson
+ * All rights reserved.
+ *
+ * WARNING: THIS IS EXPERIMENTAL SECURITY SOFTWARE THAT MUST NOT BE RELIED
+ * ON IN PRODUCTION SYSTEMS. IT WILL BREAK YOUR SOFTWARE IN NEW AND
+ * UNEXPECTED WAYS.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapability/libcapability_fdlist.c#1 $
+ */
+
+#include <errno.h>
+#include <libcapability.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+struct lc_fdlist_entry {
+
+ unsigned int sysoff; /* offset of e.g. "org.freebsd.rtld-elf-cap" */
+ unsigned int syslen; /* length of above */
+
+ unsigned int idoff; /* offset of variable ID e.g. "libs" */
+ unsigned int idlen; /* length of above */
+
+ unsigned int nameoff; /* offset of entry name (e.g. "libc.so.7") */
+ unsigned int namelen; /* length of above */
+
+ int fd; /* the file descriptor */
+};
+
+
+struct lc_fdlist {
+
+ unsigned int count; /* number of entries */
+ unsigned int capacity; /* entries that we can hold */
+
+ unsigned int namelen; /* bytes of name data */
+ unsigned int namecapacity; /* bytes of name data we can hold */
+
+ pthread_mutex_t lock; /* for thread safety */
+
+ struct lc_fdlist_entry entries[]; /* entries in the descriptor list */
+
+ /* followed by bytes of name data */
+};
+
+
+
+
+#define LOCK(l) pthread_mutex_lock(&((l)->lock));
+#define UNLOCK(l) pthread_mutex_unlock(&((l)->lock));
+
+/* Where an FD list's name byte array starts */
+char* lc_fdlist_names(struct lc_fdlist *l);
+
+
+
+#define INITIAL_ENTRIES 16
+#define INITIAL_NAMEBYTES (64 * INITIAL_ENTRIES)
+
+
+struct lc_fdlist*
+lc_fdlist_new(void) {
+
+ int bytes = sizeof(struct lc_fdlist)
+ + INITIAL_ENTRIES * sizeof(struct lc_fdlist_entry)
+ + INITIAL_NAMEBYTES;
+
+ struct lc_fdlist *fdlist = malloc(bytes);
+ if (fdlist == NULL) return (NULL);
+
+ fdlist->count = 0;
+ fdlist->capacity = INITIAL_ENTRIES;
+ fdlist->namelen = 0;
+ fdlist->namecapacity = INITIAL_NAMEBYTES;
+
+ if (pthread_mutex_init(&fdlist->lock, NULL)) {
+ free(fdlist);
+ return NULL;
+ }
+
+ return fdlist;
+}
+
+
+struct lc_fdlist*
+lc_fdlist_dup(struct lc_fdlist *orig) {
+
+ LOCK(orig);
+
+ int size = lc_fdlist_size(orig);
+
+ struct lc_fdlist *copy = malloc(size);
+ if (copy == NULL) return (NULL);
+
+ UNLOCK(orig);
+
+ return copy;
+}
+
+
+void
+lc_fdlist_free(struct lc_fdlist *l) {
+
+ LOCK(l);
+
+ pthread_mutex_destroy(&l->lock);
+ free(l);
+}
+
+
+
+int
+lc_fdlist_add(struct lc_fdlist **fdlist,
+ const char *subsystem, const char *id,
+ const char *name, int fd) {
+
+ struct lc_fdlist *l = *fdlist;
+
+ LOCK(l);
+
+ /* do we need more entry space? */
+ if (l->count == l->capacity) {
+
+ /* move name data out of the way */
+ char *tmp = NULL;
+ if (l->namelen > 0) {
+ tmp = malloc(l->namelen);
+ if (tmp == NULL) {
+ UNLOCK(l);
+ return (-1);
+ }
+
+ memcpy(tmp, lc_fdlist_names(l), l->namelen);
+ }
+
+ /* double the number of available entries */
+ int namebytes_per_entry = l->namecapacity / l->capacity;
+ int newnamebytes = l->capacity * namebytes_per_entry;
+
+ int newsize = lc_fdlist_size(l) + newnamebytes
+ + l->capacity * sizeof(struct lc_fdlist_entry);
+
+ struct lc_fdlist *copy = realloc(l, newsize);
+ if (copy == NULL) {
+ free(tmp);
+ UNLOCK(l);
+ return (-1);
+ }
+
+ copy->capacity *= 2;
+ copy->namecapacity += newnamebytes;
+
+ /* copy name bytes back */
+ if (copy->namelen > 0)
+ memcpy(lc_fdlist_names(copy), tmp, copy->namelen);
+
+ free(tmp);
+
+ *fdlist = copy;
+ l = *fdlist;
+ }
+
+
+ /* do we need more name space? */
+ int subsyslen = strlen(subsystem);
+ int idlen = strlen(id);
+ int namelen = strlen(name);
+
+ if ((l->namelen + subsyslen + idlen + namelen) >= l->namecapacity) {
+
+ /* double the name capacity */
+ struct lc_fdlist* enlarged
+ = realloc(l, lc_fdlist_size(l) + l->namecapacity);
+
+ if (enlarged == NULL) {
+ UNLOCK(l);
+ return (-1);
+ }
+
+ enlarged->namecapacity *= 2;
+ *fdlist = enlarged;
+ l = *fdlist;
+ }
+
+
+ /* create the new entry */
+ struct lc_fdlist_entry *entry = l->entries + l->count;
+
+ entry->fd = fd;
+
+ char *names = lc_fdlist_names(l);
+ char *head = names + l->namelen;
+
+ strncpy(head, subsystem, subsyslen + 1);
+ entry->sysoff = (head - names);
+ entry->syslen = subsyslen;
+ head += subsyslen + 1;
+
+ strncpy(head, id, idlen + 1);
+ entry->idoff = (head - names);
+ entry->idlen = idlen;
+ head += idlen + 1;
+
+ strncpy(head, name, namelen + 1);
+ entry->nameoff = (head - names);
+ entry->namelen = namelen + 1;
+ head += namelen + 1;
+
+ l->count++;
+ l->namelen = (head - names);
+
+ UNLOCK(l);
+
+ return 0;
+}
+
+
+int
+lc_fdlist_addcap(struct lc_fdlist **fdlist,
+ const char *subsystem, const char *id,
+ const char *name, int fd, cap_rights_t rights) {
+
+ int cap = cap_new(fd, rights);
+
+ return lc_fdlist_add(fdlist, subsystem, id, name, cap);
+}
+
+
+int
+lc_fdlist_lookup(struct lc_fdlist *l,
+ const char *subsystem, const char *id, char **name, int *fdp,
+ int *pos) {
+
+ LOCK(l);
+
+ int successful = 0;
+ const char *names = lc_fdlist_names(l);
+
+ for (unsigned int i = (pos ? *pos + 1 : 0); i < l->count; i++) {
+
+ struct lc_fdlist_entry *entry = l->entries + i;
+
+ if (!strncmp(subsystem, names + entry->sysoff, entry->syslen + 1)
+ && !strncmp(id, names + entry->idoff, entry->idlen + 1)) {
+
+ /* found a matching entry! */
+ *name = malloc(entry->namelen + 1);
+ strncpy(*name, names + entry->nameoff, entry->namelen + 1);
+
+ *fdp = entry->fd;
+
+ if (pos) *pos = i;
+ successful = 1;
+
+ break;
+ }
+ }
+
+ UNLOCK(l);
+
+ if (successful) return 0;
+ else {
+ errno = ENOENT;
+ return (-1);
+ }
+}
+
+
+int
+lc_fdlist_size(struct lc_fdlist* l) {
+
+ LOCK(l);
+
+ if (l == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ int size = sizeof(struct lc_fdlist)
+ + l->capacity * sizeof(struct lc_fdlist_entry)
+ + l->namecapacity;
+
+ UNLOCK(l);
+
+ return size;
+}
+
+
+char*
+lc_fdlist_names(struct lc_fdlist *l) {
+
+ LOCK(l);
+
+ if (l == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ char *names = ((char*) l) + lc_fdlist_size(l) - l->namecapacity;
+
+ UNLOCK(l);
+
+ return names;
+}
+
More information about the svn-src-projects
mailing list