PERFORCE change 173958 for review
Jonathan Anderson
jona at FreeBSD.org
Sat Jan 30 15:54:55 UTC 2010
http://p4web.freebsd.org/chv.cgi?CH=173958
Change 173958 by jona at jona-belle-freebsd8 on 2010/01/30 15:53:54
File descriptor reordering via lc_fdlist_reorder()
Affected files ...
.. //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#5 edit
.. //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_fdlist.c#5 edit
.. //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_host.c#7 edit
.. //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_internal.h#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/fdlist/fdlist.c#7 edit
Differences ...
==== //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#5 (text+ko) ====
@@ -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#4 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#5 $
*/
#ifndef _LIBCAPABILITY_H_
@@ -103,6 +103,23 @@
char **name, int *fdp, int *pos);
/*
+ * Look up a file descriptor without a name. Repeated calls to this function will
+ * iterate through all descriptors in the list.
+ */
+int lc_fdlist_getentry(struct lc_fdlist *l,
+ char **subsystem, char **classname,
+ char **name, int *fdp, int *pos);
+
+/*
+ * Reorder FD list (WARNING: this could be dangerous!).
+ *
+ * This call takes all of the file descriptors in the FD list, and moves them into
+ * a continuous array, starting at the FD given by 'start'. Any file descriptors
+ * above 'start' which are not in the FD list are closed.
+ */
+int lc_fdlist_reorder(struct lc_fdlist *l);
+
+/*
* Capability interfaces.
*/
int lc_limitfd(int fd, cap_rights_t rights);
==== //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_fdlist.c#5 (text+ko) ====
@@ -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_fdlist.c#4 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_fdlist.c#5 $
*/
#include <sys/mman.h>
@@ -52,8 +52,8 @@
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 classoff; /* offset of variable ID e.g. "libs" */
+ unsigned int classlen; /* length of above */
unsigned int nameoff; /* offset of entry name (e.g. "libc.so.7") */
unsigned int namelen; /* length of above */
@@ -243,10 +243,10 @@
/* do we need more name space? */
int subsyslen = strlen(subsystem);
- int idlen = strlen(id);
+ int classlen = strlen(id);
int namelen = strlen(name);
- if ((l->namelen + subsyslen + idlen + namelen) >= l->namecapacity) {
+ if ((l->namelen + subsyslen + classlen + namelen) >= l->namecapacity) {
/* double the name capacity */
struct lc_fdlist* enlarged
@@ -276,10 +276,10 @@
entry->syslen = subsyslen;
head += subsyslen + 1;
- strncpy(head, id, idlen + 1);
- entry->idoff = (head - names);
- entry->idlen = idlen;
- head += idlen + 1;
+ strncpy(head, id, classlen + 1);
+ entry->classoff = (head - names);
+ entry->classlen = classlen;
+ head += classlen + 1;
strncpy(head, name, namelen + 1);
entry->nameoff = (head - names);
@@ -313,20 +313,28 @@
if (l == NULL) {
errno = EINVAL;
- return -1;
+ return (-1);
}
LOCK(l);
+ if ((pos != NULL) && (*pos >= (int) l->count)) {
+ UNLOCK(l);
+ errno = EINVAL;
+ return (-1);
+ }
+
int successful = 0;
const char *names = lc_fdlist_names(l);
- for (unsigned int i = (pos ? *pos + 1 : 0); i < l->count; i++) {
+ for (unsigned int i = (pos ? *pos : 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)) {
+ if ((!subsystem ||
+ !strncmp(subsystem, names + entry->sysoff, entry->syslen + 1))
+ && (!id ||
+ !strncmp(id, names + entry->classoff, entry->classlen + 1))) {
/* found a matching entry! */
*name = malloc(entry->namelen + 1);
@@ -334,7 +342,7 @@
*fdp = entry->fd;
- if (pos) *pos = i;
+ if (pos) *pos = i + 1;
successful = 1;
break;
@@ -352,6 +360,97 @@
int
+lc_fdlist_getentry(struct lc_fdlist *l,
+ char **subsystem, char **classname,
+ char **name, int *fdp, int *pos) {
+
+ LOCK(l);
+
+ if ((pos == NULL) || (*pos < 0) || (*pos >= (int) l->count)
+ || (subsystem == NULL) || (classname == NULL)
+ || (name == NULL) || (fdp == NULL)) {
+
+ errno = EINVAL;
+ return (-1);
+ }
+
+ struct lc_fdlist_entry *entry = l->entries + *pos;
+ char *names = lc_fdlist_names(l);
+ int size = entry->syslen + entry->classlen + entry->namelen;
+ char *head = malloc(size);
+
+ strncpy(head, names + entry->sysoff, entry->syslen + 1);
+ *subsystem = head;
+ head += size;
+
+ strncpy(head, names + entry->classoff, entry->classlen + 1);
+ *classname = head;
+ head += size;
+
+ strncpy(head, names + entry->nameoff, entry->namelen + 1);
+ *name = head;
+ head += size;
+
+ *fdp = entry->fd;
+
+ UNLOCK(l);
+
+ (*pos)++;
+
+ return 0;
+}
+
+
+int
+lc_fdlist_reorder(struct lc_fdlist *l) {
+
+ LOCK(l);
+
+ /* Do we really need to do this? */
+ if (l->count == 0)
+ return (0);
+
+ /*
+ * Identify the highest source file descriptor we care about so that
+ * when we play the dup2() rearranging game, we don't overwrite any
+ * we care about.
+ */
+ int highestfd = -1;
+ for (unsigned int i = 0; i < l->count; i++) {
+ if (l->entries[i].fd > highestfd)
+ highestfd = l->entries[i].fd;
+ }
+ highestfd++; /* Don't tread on the highest */
+
+ /*
+ * First, move all our descriptors up the range.
+ */
+ for (unsigned int i = 0; i < l->count; i++) {
+ if (dup2(l->entries[i].fd, highestfd + i) < 0)
+ return (-1);
+ }
+
+ /*
+ * Now put them back.
+ */
+ for (unsigned int i = 0; i < l->count; i++) {
+ if (dup2(highestfd + i, i) < 0)
+ return (-1);
+
+ l->entries[i].fd = i;
+ }
+
+ /*
+ * Close the descriptors that we moved, as well as any others that
+ * were left open by the caller.
+ */
+ closefrom(l->count);
+
+ return 0;
+}
+
+
+int
lc_fdlist_size(struct lc_fdlist* l) {
LOCK(l);
==== //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_host.c#7 (text+ko) ====
@@ -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_host.c#6 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_host.c#7 $
*/
#include <sys/param.h>
@@ -161,26 +161,62 @@
/*
* Create an anonymous shared memory segment for the FD list.
*/
- if (fds != NULL) {
- shmfd = shm_open(SHM_ANON, O_RDWR, 0600);
- if (shmfd < 0)
- return;
- fdlistsize = lc_fdlist_size(fds);
- if (ftruncate(shmfd, fdlistsize) < 0)
- return;
+ if (fds == NULL) fds = lc_fdlist_new();
+
+ shmfd = shm_open(SHM_ANON, O_RDWR, 0600);
+ if (shmfd < 0)
+ return;
+ fdlistsize = lc_fdlist_size(fds);
+ if (ftruncate(shmfd, fdlistsize) < 0)
+ return;
+
+ /*
+ * Map it and copy the list.
+ */
+ shm = mmap(NULL, fdlistsize, PROT_READ | PROT_WRITE,
+ MAP_NOSYNC | MAP_SHARED, shmfd, 0);
+ if (shm == MAP_FAILED)
+ return;
+ memcpy(shm, fds, fdlistsize);
+ if (munmap(shm, fdlistsize))
+ return;
+
+ if (lc_fdlist_addcap(&fds, "org.freebsd.libcapsicum", "/dev/null", "",
+ fd_devnull, LIBCAPABILITY_CAPMASK_DEVNULL) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.libcapsicum", "sandbox", "",
+ fd_sandbox, LIBCAPABILITY_CAPMASK_SANDBOX) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.libcapsicum", "socket", "",
+ fd_sock, LIBCAPABILITY_CAPMASK_SOCK) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.rtld-elf-cap", "ldso", "",
+ fd_ldso, LIBCAPABILITY_CAPMASK_LDSO) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.rtld-elf-cap", "lib", "libc",
+ fd_libc, LIBCAPABILITY_CAPMASK_LIB) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.rtld-elf-cap", "lib", "libcapsicum",
+ fd_libcapsicum, LIBCAPABILITY_CAPMASK_LIB) < 0)
+ return;
+ if (lc_fdlist_addcap(&fds, "org.freebsd.rtld-elf-cap", "lib", "libsbuf",
+ fd_libsbuf, LIBCAPABILITY_CAPMASK_LIB) < 0)
+ return;
+/*
+ {
+ int pos = 0;
+ char *subsystem;
+ char *class;
+ char *name;
+ int fd;
- /*
- * Map it and copy the list.
- */
- shm = mmap(NULL, fdlistsize, PROT_READ | PROT_WRITE,
- MAP_NOSYNC | MAP_SHARED, shmfd, 0);
- if (shm == MAP_FAILED)
- return;
- memcpy(shm, fds, fdlistsize);
- if (munmap(shm, fdlistsize))
- return;
+ while (lc_fdlist_getentry(fds, &subsystem, &class, &name, &fd, &pos)
+ >= 0) {
+ printf("%d\t'%s'.'%s': '%s' (%d)\n",
+ pos, subsystem, class, name, fd);
+ }
}
-
+*/
if (lc_limitfd(fd_devnull, LIBCAPABILITY_CAPMASK_DEVNULL) < 0)
return;
if (lc_limitfd(fd_sandbox, LIBCAPABILITY_CAPMASK_SANDBOX) < 0)
==== //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_internal.h#3 (text+ko) ====
@@ -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_internal.h#2 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_internal.h#3 $
*/
#ifndef _LIBCAPABILITY_INTERNAL_H_
@@ -46,6 +46,8 @@
pid_t lcs_pid;
};
+
+
/*
* Communications flags for recv/send calls (lc_flags).
*/
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/fdlist/fdlist.c#7 (text+ko) ====
@@ -47,8 +47,7 @@
-int add_junk(struct lc_fdlist**);
-int find_junk(struct lc_fdlist*);
+void print_fdlist(struct lc_fdlist* fds);
/*
@@ -57,25 +56,48 @@
int
main(int argc, char *argv[])
{
- printf("fdlist\n");
+ printf("fdlist: PID %d\n", getpid());
+
+ /* create a shared memory segment for FDs */
+ int shmfd = shm_open(SHM_ANON, O_RDWR, 0600);
+ if (shmfd < 0)
+ err(-1, "Error opening shared memory");
+
/* create an FD list and add some junk to it */
struct lc_fdlist *fds = lc_fdlist_new();
if (fds == NULL) err(-1, "Error in lc_fdlist_new()");
- lc_fdlist_add(&fds, "org.freebsd.Capsicum", "testfile",
+ lc_fdlist_addcap(&fds, "org.freebsd.Capsicum.fdlist", "stdin", "",
+ 0, CAP_READ);
+
+ lc_fdlist_addcap(&fds, "org.freebsd.Capsicum.fdlist", "stdout", "",
+ 1, CAP_WRITE | CAP_SEEK);
+
+ lc_fdlist_addcap(&fds, "org.freebsd.Capsicum.fdlist", "stderr", "",
+ 2, CAP_WRITE | CAP_SEEK);
+
+ lc_fdlist_add(&fds, "org.freebsd.Capsicum.fdlist", "testfile",
"/etc/passwd", open("/etc/passwd", O_RDONLY));
- lc_fdlist_addcap(&fds, "org.freebsd.Capsicum", "testfile",
+ lc_fdlist_addcap(&fds, "org.freebsd.Capsicum.fdlist", "testfile",
"/etc/group", open("/etc/group", O_RDONLY), CAP_READ);
+ lc_fdlist_add(&fds, "org.freebsd.Capsicum.fdlist", "fdlist",
+ "<anonymous POSIX SHM>", shmfd);
- if (add_junk(&fds) < 0) err(-1, "Error in add_junk()");
- if (find_junk(fds) < 0) err(-1, "Error in find_junk()");
+ print_fdlist(fds);
+
+ printf("Reordering FDs...\n");
+ if (lc_fdlist_reorder(fds))
+ err(-1, "lc_fdlist_reorder(fds) failed");
+
+ print_fdlist(fds);
- /* copy it into a shared memory segment and see if it still works */
- int shmfd = shm_open(SHM_ANON, O_RDWR, 0600);
- if (shmfd < 0)
- err(-1, "Error opening shared memory");
+ char *name;
+ if (lc_fdlist_lookup(fds, "org.freebsd.Capsicum.fdlist", "fdlist",
+ &name, &shmfd, NULL) < 0) {
+ err(-1, "Error in lc_fdlist_lookup()");
+ }
int size = lc_fdlist_size(fds);
if (ftruncate(shmfd, size) < 0)
@@ -91,9 +113,6 @@
memcpy(shm, fds, lc_fdlist_size(fds));
- struct lc_fdlist *copy = (struct lc_fdlist*) shm;
- if (find_junk(copy) < 0) err(-1, "Error in find_junk(copy)");
-
printf("Starting sandbox...\n");
@@ -120,55 +139,38 @@
printf("cap_main() alive\n"); fflush(stdout);
struct lc_fdlist *global_fdlist = lc_fdlist_global();
- int result = find_junk(global_fdlist);
+ printf("Received FD list:\n"); fflush(stdout);
- if (result < 0) err(-1, "Error in find_junk(global_fdlist)");
- else if (result == 0) printf("find_junk() found no FD entries\n");
+ int pos = 0;
+ char *subsystem;
+ char *class;
+ char *name;
+ int fd;
- struct lc_fdlist *copy = lc_fdlist_dup(global_fdlist);
- result = find_junk(copy);
+ while (lc_fdlist_getentry(global_fdlist, &subsystem, &class,
+ &name, &fd, &pos) >= 0)
+ printf("%d\t'%s'.'%s': '%s' (%d)\n",
+ pos, subsystem, class, name, fd);
- if (result < 0) err(-1, "Error in find_junk(copy)");
- else if (result == 0) printf("find_junk() found no FD entries\n");
+ printf("OK.\n");
- printf("Received FD list OK\n"); fflush(stdout);
-
return 0;
}
-int add_junk(struct lc_fdlist **fds)
-{
- for (int i = 0; i < 20; i++)
- if (lc_fdlist_add(fds, "org.freebsd.Capsicum", "testjunk",
- "garbage", 50 + i) < 0)
- return -1;
- return 0;
-}
-
-int find_junk(struct lc_fdlist *fds)
+void print_fdlist(struct lc_fdlist* fds)
{
int pos = 0;
- int parsed = 0;
+ char *subsystem;
+ char *class;
+ char *name;
+ int fd;
- for (int i = 0; i < 20; i++) {
- char *name;
- int value;
-
- if (lc_fdlist_lookup(fds, "org.freebsd.Capsicum", "testjunk",
- &name, &value, &pos) < 0)
- return -1;
-
- if (strcmp("garbage", name))
- warnx("i=%i\tGot '%s' instead of 'garbage'", i, name);
-
- if (value != 50 + i)
- warnx("i=%i\tGot 'FD' %i instead of %i", i, value, 50 + i);
-
- parsed++;
+ while (lc_fdlist_getentry(fds, &subsystem, &class, &name, &fd, &pos)
+ >= 0) {
+ printf("%d\t'%s'.'%s': '%s' (%d)\n",
+ pos, subsystem, class, name, fd);
}
-
- return parsed;
}
More information about the p4-projects
mailing list