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