Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Jun 2010 15:24:19 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r208710 - projects/capabilities8/lib/libcapsicum
Message-ID:  <201006011524.o51FOJhB069635@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Tue Jun  1 15:24:19 2010
New Revision: 208710
URL: http://svn.freebsd.org/changeset/base/208710

Log:
  Merge c177191, c177355, c177356, 178149 from the p4 TrustedBSD Capabilities
  branch to capabilities8:
  
    Various libcapsicum improvements:
  
    Talk about 'executable' rather than 'binary' in the FD list.
  
    Added lc_fdlist_print().
  
    Create LD_PRELOAD for sanbdox.
  
    Added lc_fdlist_find(), changed whitespace in lc_fdlist_lookup() for
      clarity.
  
  Submitted by:	jona

Modified:
  projects/capabilities8/lib/libcapsicum/libcapsicum.h
  projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c
  projects/capabilities8/lib/libcapsicum/libcapsicum_host.c

Modified: projects/capabilities8/lib/libcapsicum/libcapsicum.h
==============================================================================
--- projects/capabilities8/lib/libcapsicum/libcapsicum.h	Tue Jun  1 15:11:29 2010	(r208709)
+++ projects/capabilities8/lib/libcapsicum/libcapsicum.h	Tue Jun  1 15:24:19 2010	(r208710)
@@ -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#12 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum.h#15 $
  */
 
 #ifndef _LIBCAPSICUM_H_
@@ -52,6 +52,7 @@ struct lc_fdlist	*lc_fdlist_new(void);
 struct lc_fdlist	*lc_fdlist_global(void);
 struct lc_fdlist	*lc_fdlist_dup(struct lc_fdlist *lfp_orig);
 void			 lc_fdlist_free(struct lc_fdlist *lfp);
+void			 lc_fdlist_print(struct lc_fdlist *lfp, int outFD);
 
 /*
  * Size of an FD list in bytes, including all associated string data.
@@ -89,6 +90,19 @@ int	lc_fdlist_addcap(struct lc_fdlist *l
 	    cap_rights_t rights);
 
 /*
+ * Open a stored file descriptor.
+ *
+ * Given a filename '/foo/bar/fubar', this function will attempt to find the file
+ * in the FD list. If that fails, it will attempt to find a parent directory in the
+ * FD list and supply a filename relative to that FD (which will be a pointer to a
+ * location within the supplied filename - do NOT free it!).
+ */
+int
+lc_fdlist_find(struct lc_fdlist *lfp, const char *subsystem,
+	    const char *classname, const char *filename,
+	    const char **relative_name);
+
+/*
  * Look up a file descriptor.
  *
  * Multiple entries with the same classname are allowed, so iterating through

Modified: projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c
==============================================================================
--- projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c	Tue Jun  1 15:11:29 2010	(r208709)
+++ projects/capabilities8/lib/libcapsicum/libcapsicum_fdlist.c	Tue Jun  1 15:24:19 2010	(r208710)
@@ -31,12 +31,13 @@
  * 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#11 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_fdlist.c#13 $
  */
 
 #include <sys/mman.h>
 #include <sys/stat.h>
 
+#define _WITH_DPRINTF
 #include <errno.h>
 #include <libcapsicum.h>
 #include <pthread.h>
@@ -202,6 +203,24 @@ lc_fdlist_free(struct lc_fdlist *lfp)
 	free(lfp);
 }
 
+void
+lc_fdlist_print(struct lc_fdlist *lfp, int outFD)
+{
+	dprintf(outFD, "FD List:\n");
+	for(int i = 0; ; )
+	{
+		char *subsystem, *classname, *name;
+		int fd;
+
+		if (lc_fdlist_getentry(lfp, &subsystem, &classname, &name, &fd, &i)
+		     < 0)
+			break;
+
+		dprintf(outFD, "% 3d:\t'%s'.'%s': '%s'\n",
+		        fd, subsystem, classname, name);
+	}
+}
+
 int
 lc_fdlist_add(struct lc_fdlist *lfp, const char *subsystem,
     const char *classname, const char *name, int fd)
@@ -248,7 +267,6 @@ lc_fdlist_add(struct lc_fdlist *lfp, con
 			memcpy(lc_fdlist_storage_names(lfsp_copy), tmp,
 			    lfsp_copy->namelen);
 
-		free(lfsp);
 		lfsp = lfp->lf_storage = lfsp_copy;
 		free(tmp);
 	}
@@ -375,6 +393,60 @@ lc_fdlist_addcap(struct lc_fdlist *fdlis
 }
 
 int
+lc_fdlist_find(struct lc_fdlist *lfp, const char *subsystem,
+	    const char *classname, const char *filename,
+	    const char **relative_name)
+{
+	int pos = 0;
+	int fd = -1;
+
+	/* try to find the file itself in the FD list */
+	size_t len = strlen(filename);
+	*relative_name = filename + len;
+
+	while (fd == -1)
+	{
+		char *dirname;
+
+		if (lc_fdlist_lookup(lfp, subsystem, classname,
+		                     &dirname, &fd, &pos) == -1)
+			break;
+
+		if (strncmp(dirname, filename, len + 1)) fd = -1;
+		free(dirname);
+	}
+
+	if (fd >= 0) return fd;
+
+
+	/* now try to find a parent directory and a relative filename */
+	*relative_name = NULL;
+	pos = 0;
+
+	while (fd == -1)
+	{
+		char *dirname;
+
+		if (lc_fdlist_lookup(lfp, subsystem, classname,
+		                     &dirname, &fd, &pos) == -1)
+			return (-1);
+
+		len = strlen(dirname);
+		if (strncmp(dirname, filename, len)) fd = -1;
+		else
+		{
+			*relative_name = filename + len;
+			if (**relative_name == '/') (*relative_name)++;
+		}
+
+		free(dirname);
+	}
+
+	return fd;
+}
+
+
+int
 lc_fdlist_lookup(struct lc_fdlist *lfp, const char *subsystem,
     const char *classname, char **name, int *fdp, int *pos)
 {
@@ -394,28 +466,30 @@ lc_fdlist_lookup(struct lc_fdlist *lfp, 
 	for (u_int i = (pos ? *pos : 0); i < lfsp->count; i++) {
 		struct lc_fdlist_entry *entry = lfsp->entries + i;
 
-		if ((!subsystem ||
-		    !strncmp(subsystem, names + entry->sysoff,
-		    entry->syslen + 1))
-		    && (!classname || !strncmp(classname, names +
-		    entry->classoff, entry->classnamelen + 1))) {
-
+		if ((!subsystem
+		     || !strncmp(subsystem, names + entry->sysoff,
+		                 entry->syslen + 1))
+		    && (!classname
+		        || !strncmp(classname, names + entry->classoff,
+		                    entry->classnamelen + 1)))
+		{
 			/* found a matching entry! */
+			successful = 1;
+			*fdp = entry->fd;
+
 			if (name) {
 				*name = malloc(entry->namelen + 1);
 				strncpy(*name, names + entry->nameoff,
 				        entry->namelen + 1);
 			}
-
-			*fdp = entry->fd;
-			if (pos != NULL) *pos = i + 1;
-			successful = 1;
+			if (pos) *pos = i + 1;
 			break;
 		}
 	}
 	UNLOCK(lfp);
 	if (successful)
 		return (0);
+
 	errno = ENOENT;
 	return (-1);
 }

Modified: projects/capabilities8/lib/libcapsicum/libcapsicum_host.c
==============================================================================
--- projects/capabilities8/lib/libcapsicum/libcapsicum_host.c	Tue Jun  1 15:11:29 2010	(r208709)
+++ projects/capabilities8/lib/libcapsicum/libcapsicum_host.c	Tue Jun  1 15:24:19 2010	(r208710)
@@ -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#17 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_host.c#19 $
  */
 
 #include <sys/param.h>
@@ -41,6 +41,7 @@
 #include <sys/socket.h>
 #include <sys/uio.h>
 
+#define _WITH_DPRINTF
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -67,6 +68,8 @@
 #define LIBCAPSICUM_CAPMASK_FDLIST	CAP_READ | CAP_WRITE | CAP_FTRUNCATE \
 					 | CAP_FSTAT | CAP_MMAP
 
+#define LIBCAPSICUM_CAPMASK_STDOUT	CAP_WRITE | CAP_SEEK | CAP_FSTAT
+
 extern char **environ;
 
 #define LD_ELF_CAP_SO		"ld-elf-cap.so.1"
@@ -123,12 +126,12 @@ lch_sandbox(int fd_sock, int fd_binary, 
 
 	if (lc_fdlist_addcap(fds, LIBCAPSICUM_FQNAME, "stdout", "",
 		STDOUT_FILENO,
-		(flags & LCH_PERMIT_STDOUT) ? CAP_WRITE | CAP_SEEK : 0) < 0)
+		(flags & LCH_PERMIT_STDOUT) ? LIBCAPSICUM_CAPMASK_STDOUT : 0) < 0)
 		err(-1, "Error in lc_fdlist_addcap(stdout)");
 
 	if (lc_fdlist_addcap(fds, LIBCAPSICUM_FQNAME, "stderr", "",
 		STDERR_FILENO,
-		(flags & LCH_PERMIT_STDERR) ? CAP_WRITE | CAP_SEEK : 0) < 0)
+		(flags & LCH_PERMIT_STDERR) ? LIBCAPSICUM_CAPMASK_STDOUT : 0) < 0)
 		err(-1, "Error in lc_fdlist_addcap(stderr)");
 
 	if (lc_fdlist_addcap(fds, LIBCAPSICUM_FQNAME, "socket", "",
@@ -143,13 +146,10 @@ lch_sandbox(int fd_sock, int fd_binary, 
 	                     fd_rtld, LIBCAPSICUM_CAPMASK_LDSO) < 0)
 		err(-1, "Error in lc_fdlist_addcap(fd_rtld)");
 
-	if (lc_fdlist_addcap(fds, RTLD_CAP_FQNAME, "binary", "",
+	if (lc_fdlist_addcap(fds, RTLD_CAP_FQNAME, "Executable", binname,
 	                     fd_binary, LIBCAPSICUM_CAPMASK_SANDBOX) < 0)
 		err(-1, "Error in lc_fdlist_addcap(fd_binary)");
 
-	if (lc_fdlist_append(fds, userfds) < 0)
-		err(-1, "Error in lc_fdlist_append()");
-
 	/*
 	 * Ask RTLD for library path descriptors.
 	 *
@@ -170,15 +170,23 @@ lch_sandbox(int fd_sock, int fd_binary, 
 			break;
 	}
 
-	for (int j = 0; j < size; j++)
-		if (lc_fdlist_addcap(fds, RTLD_CAP_FQNAME, "libdir", "",
+	for (int j = 0; j < size; j++) {
+		if (lc_fdlist_addcap(fds, RTLD_CAP_FQNAME, "LibraryDirectory", "",
 		    libdirs[j], LIBCAPSICUM_CAPMASK_LIBDIR) < 0)
 			err(-1, "Error in lc_fdlist_addcap(libdirs[%d]: %d)",
 			    j, libdirs[j]);
+	}
+
+	/* Append user FD list and reorder the descriptors */
+	if (lc_fdlist_append(fds, userfds) < 0)
+		err(-1, "Error in lc_fdlist_append()");
 
 	if (lc_fdlist_reorder(fds) < 0)
 		err(-1, "Error in lc_fdlist_reorder()");
 
+
+
+
 	/*
 	 * Find the fdlist shared memory segment.
 	 */
@@ -219,16 +227,16 @@ lch_sandbox(int fd_sock, int fd_binary, 
 	/*
 	 * Find the binary for RTLD.
 	 */
-	if (lc_fdlist_lookup(fds, RTLD_CAP_FQNAME, "binary", NULL,
+	if (lc_fdlist_lookup(fds, RTLD_CAP_FQNAME, "Executable", NULL,
 	    &fd_binary, NULL) < 0)
-		err(-1, "Error in lc_fdlist_lookup(RTLD binary)");
+		err(-1, "Error in lc_fdlist_lookup(Executable)");
 
 	sprintf(tmp, "%d", fd_binary);
 	if (setenv("LD_BINARY", tmp, 1) != 0)
 		err(-1, "Error in setenv(LD_BINARY)");
 
 	/*
-	 * Build LD_LIBRARY_DIRS for RTLD.
+	 * Build LD_LIBRARY_DIRS and LD_PRELOAD for RTLD.
 	 *
 	 * NOTE: This is FreeBSD-specific; porting to other operating systems
 	 * will require dynamic linkers capable of operating on file
@@ -240,8 +248,9 @@ lch_sandbox(int fd_sock, int fd_binary, 
 
 	{
 		int fd;
-		while (lc_fdlist_lookup(fds, RTLD_CAP_FQNAME, "libdir", NULL,
-		    &fd, &pos) >= 0)
+		pos = 0;
+		while (lc_fdlist_lookup(fds, RTLD_CAP_FQNAME, "LibraryDirectory",
+		       NULL, &fd, &pos) >= 0)
 			sbuf_printf(sbufp, "%d:", fd);
 	}
 
@@ -252,10 +261,30 @@ lch_sandbox(int fd_sock, int fd_binary, 
 		err(-1, "Error in setenv(LD_LIBRARY_DIRS)");
 	sbuf_delete(sbufp);
 
+	sbufp = sbuf_new_auto();
+	if (sbufp == NULL)
+		err(-1, "Error in sbuf_new_auto()");
+
+	{
+		int fd;
+		pos = 0;
+		while (lc_fdlist_lookup(fds, RTLD_CAP_FQNAME, "PreloadLibrary",
+		       NULL, &fd, &pos) >= 0)
+			sbuf_printf(sbufp, "%d:", fd);
+	}
+
+	sbuf_finish(sbufp);
+	if (sbuf_overflowed(sbufp))
+		err(-1, "sbuf_overflowed()");
+	if (setenv("LD_PRELOAD", sbuf_data(sbufp), 1) == -1)
+		err(-1, "Error in setenv(LD_PRELOAD)");
+	sbuf_delete(sbufp);
+
 	if (cap_enter() < 0)
 		err(-1, "cap_enter() failed");
 
 	(void)fexecve(fd_rtld, argv, environ);
+	dprintf(2, "ERROR: fexecve() failed; errno = %d\n", errno);
 }
 
 int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006011524.o51FOJhB069635>