Date: Sat, 30 Jan 2010 20:37:47 +0000 (UTC) From: Robert Watson <rwatson@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r203246 - projects/capabilities8/lib/libcapsicum Message-ID: <201001302037.o0UKbl7a001875@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rwatson Date: Sat Jan 30 20:37:47 2010 New Revision: 203246 URL: http://svn.freebsd.org/changeset/base/203246 Log: Add missed file from c173855: Changed the libcapsicum startfd API to accept an lc_fdlist (no implementation changes yet) Submitted by: Jonathan Anderson <jonathan.anderson at cl.cam.ac.uk> Added: projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c Modified: projects/capabilities8/lib/libcapsicum/libcapsicum.h Modified: projects/capabilities8/lib/libcapsicum/libcapsicum.h ============================================================================== --- projects/capabilities8/lib/libcapsicum/libcapsicum.h Sat Jan 30 20:32:23 2010 (r203245) +++ projects/capabilities8/lib/libcapsicum/libcapsicum.h Sat Jan 30 20:37:47 2010 (r203246) @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#2 $ + * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#3 $ */ #ifndef _LIBCAPABILITY_H_ @@ -57,11 +57,12 @@ struct lc_library { /* 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_global(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); Added: projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c Sat Jan 30 20:37:47 2010 (r203246) @@ -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/libcapsicum/libcapsicum_fdlist.c#1 $ + */ + +#include <errno.h> +#include <libcapsicum.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; +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001302037.o0UKbl7a001875>