Date: Sat, 30 Jan 2010 15:54:54 GMT From: Jonathan Anderson <jona@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 173958 for review Message-ID: <201001301554.o0UFss54070410@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=173958 Change 173958 by jona@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; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001301554.o0UFss54070410>