Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Feb 2010 11:22:03 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r203425 - in projects/capabilities8: lib/libcapsicum libexec/rtld-elf
Message-ID:  <201002031122.o13BM3Mr078200@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Wed Feb  3 11:22:03 2010
New Revision: 203425
URL: http://svn.freebsd.org/changeset/base/203425

Log:
  Merge c174211, c174213, c174214, and c174218 from the p4 TrustedBSD
  Capabilities branch to capabilities8:
  
    There's no IN_CAP_MODE definition for libcapsicum, so just test for
    a negative fd_rtld before closing.
  
    Improve style alignment of capability-related code with existing
    rtld style (which isn't style(9)).
  
    Add missing free of string and explicit NULL return on error.
    Keep a running count of valid file descriptors in the directory
    length array, rather than marking unused ones as (-1).  This avoids
    several loops.  While here, fix a (+ sizeof(int)) into a
    (* sizeof(int)) and a few other nits.
  
  Sponsored by:	Google, Inc.

Modified:
  projects/capabilities8/lib/libcapsicum/libcapsicum_host.c
  projects/capabilities8/libexec/rtld-elf/rtld.c

Modified: projects/capabilities8/lib/libcapsicum/libcapsicum_host.c
==============================================================================
--- projects/capabilities8/lib/libcapsicum/libcapsicum_host.c	Wed Feb  3 11:12:03 2010	(r203424)
+++ projects/capabilities8/lib/libcapsicum/libcapsicum_host.c	Wed Feb  3 11:22:03 2010	(r203425)
@@ -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#15 $
+ * $P4: //depot/projects/trustedbsd/capabilities/src/lib/libcapsicum/libcapsicum_host.c#16 $
  */
 
 #include <sys/param.h>
@@ -312,9 +312,8 @@ lch_startfd(int fd_binary, const char *b
 		    binname, argv, fds);
 		exit(-1);
 	}
-#ifndef IN_CAP_MODE
-	close(fd_rtld);
-#endif
+	if (fd_rtld != -1)
+		close(fd_rtld);
 	close(fd_sockpair[1]);
 
 	lcsp->lcs_fd_procdesc = fd_procdesc;
@@ -330,10 +329,8 @@ out_error:
 		close(fd_sockpair[0]);
 	if (fd_sockpair[1] != -1)
 		close(fd_sockpair[1]);
-#ifndef IN_CAP_MODE
 	if (fd_rtld != -1)
 		close(fd_rtld);
-#endif
 	if (lcsp != NULL)
 		free(lcsp);
 	errno = error;

Modified: projects/capabilities8/libexec/rtld-elf/rtld.c
==============================================================================
--- projects/capabilities8/libexec/rtld-elf/rtld.c	Wed Feb  3 11:12:03 2010	(r203424)
+++ projects/capabilities8/libexec/rtld-elf/rtld.c	Wed Feb  3 11:22:03 2010	(r203425)
@@ -188,7 +188,9 @@ static bool dangerous_ld_env;	/* True if
 static char *ld_bind_now;	/* Environment variable for immediate binding */
 static char *ld_debug;		/* Environment variable for debugging */
 static int *ld_library_dirs = NULL; /* File descriptors of lib path (end: -1) */
+static int ld_library_dirs_done; /* ld_library_dirs has been initialized */
 static int ld_library_dirlen;	/* Capacity of ld_library_dirs */
+static int ld_library_dircount;	/* Number of entries in ld_library_dirs */
 #ifndef IN_RTLD_CAP
 static char *ld_library_path;	/* Environment variable for search path */
 static char *ld_preload;	/* Environment variable for libraries to
@@ -251,7 +253,6 @@ static func_ptr_type exports[] = {
     (func_ptr_type) &ld_insandbox,
 #endif
     (func_ptr_type) &ld_libdirs,
- 
     NULL
 };
 
@@ -836,19 +837,19 @@ origin_subst(const char *real, const cha
 static void *
 find_capstart(const Obj_Entry *obj)
 {
-	const char *capstart_str = "_capstart";
-	const Elf_Sym *def;
-	const Obj_Entry *defobj;
-	unsigned long hash;
+    const char *capstart_str = "_capstart";
+    const Elf_Sym *def;
+    const Obj_Entry *defobj;
+    unsigned long hash;
 
-	hash = elf_hash(capstart_str);
-	def = symlook_default(capstart_str, hash, obj, &defobj, NULL,
-	    SYMLOOK_IN_PLT);
-	if (def == NULL)
-		return (NULL);
-	if (ELF_ST_TYPE(def->st_info) != STT_FUNC)
-		return (NULL);
-	return (make_function_pointer(def, defobj));
+    hash = elf_hash(capstart_str);
+    def = symlook_default(capstart_str, hash, obj, &defobj, NULL,
+	SYMLOOK_IN_PLT);
+    if (def == NULL)
+	return (NULL);
+    if (ELF_ST_TYPE(def->st_info) != STT_FUNC)
+	return (NULL);
+    return (make_function_pointer(def, defobj));
 }
 #endif
 
@@ -1236,23 +1237,24 @@ elf_hash(const char *name)
 
 #ifdef IN_RTLD_CAP
 /*
- * Find the library with the given name, and return an open file descriptor to it.
+ * Find the library with the given name, and return an open file descriptor
+ * to it.
  */
 static int
-find_library_fd(const char *name) {
-
-    if (ld_library_dirs == NULL)
-	    init_libdirs();
-
-    for (int i = 0; (i < ld_library_dirlen) && (ld_library_dirs[i] != -1); i++) {
+find_library_fd(const char *name)
+{
+    int fd, i;
 
-	int fd = openat(ld_library_dirs[i], name, O_RDONLY);
+    if (!ld_library_dirs_done)
+	init_libdirs();
+    for (i = 0; i < ld_library_dircount); i++) {
+	fd = openat(ld_library_dirs[i], name, O_RDONLY);
 	if (fd >= 0)
-		return fd;
+	    return (fd);
     }
-
     return (-1);
 }
+
 #else
 /*
  * Find the library with the given name, and return its full pathname.
@@ -1664,26 +1666,26 @@ load_object(const char *name, const Obj_
     path = xstrdup(name);
     if ((fd = find_library_fd(path)) < 0) {
 	_rtld_error("Unable to find \"%s\" in LD_LIBRARY_DIRS", path);
+	free(path);
+	return NULL;
     }
 #else
-    if (fd == -1) {
-	path = find_library(name, refobj);
-	if (path == NULL)
+    path = find_library(name, refobj);
+    if (path == NULL)
 	return NULL;
 
-	/*
-	 * If we didn't find a match by pathname, open the file and check
-	 * again by device and inode.  This avoids false mismatches caused
-	 * by multiple links or ".." in pathnames.
-	 *
-	 * To avoid a race, we open the file and use fstat() rather than
-	 * using stat().
-	 */
-	if ((fd = open(path, O_RDONLY)) == -1) {
+    /*
+     * If we didn't find a match by pathname, open the file and check
+     * again by device and inode.  This avoids false mismatches caused
+     * by multiple links or ".." in pathnames.
+     *
+     * To avoid a race, we open the file and use fstat() rather than
+     * using stat().
+     */
+    if ((fd = open(path, O_RDONLY)) == -1) {
 	_rtld_error("Cannot open \"%s\"", path);
 	free(path);
 	return NULL;
-	}
     }
 #endif
     if (fstat(fd, &sb) == -1) {
@@ -2114,42 +2116,48 @@ search_library_path(const char *name, co
 
 /*
  * Add a file descriptor to ld_library_dirs.
+ *
+ * XXX: This may be called from either the rtld startup code, or from
+ * ld_libdirs.  We have no way to distinguish them on error, so die()
+ * unconditionally.  Perhaps the latter case should allow graceful failure.
+ *
+ * XXX: Synchronization?
  */
 static void
-add_libdir_fd(int fd) {
-
-	if (ld_library_dirs == NULL) {
-	    /* Initialize the FD list. */
-
-	    ld_library_dirlen = INITIAL_FDLEN;
-	    ld_library_dirs = xmalloc(ld_library_dirlen * sizeof(int));
-	    memset(ld_library_dirs, 0xff, ld_library_dirlen * sizeof(int));
-	}
-
-	/* Find the next available FD slot. */
-	int i;
-	for (i = 0; (i < ld_library_dirlen) && (ld_library_dirs[i] != -1); i++) ;
-
-	if (i == ld_library_dirlen) {
-	    /* We need more space. */
-	    int old_size = ld_library_dirlen + sizeof(int);
+add_libdir_fd(int fd)
+{
 
-	    ld_library_dirlen *= 2;
-	    ld_library_dirs = realloc(ld_library_dirs, 2 * old_size);
-	    memset(ld_library_dirs + old_size, 0xff, old_size);
+    /* Initialize the FD list. */
+    if (!ld_library_dirs_done) {
+	ld_library_dirlen = INITIAL_FDLEN;
+	ld_library_dircount = 0;
+	ld_library_dirs = xmalloc(ld_library_dirlen * sizeof(int));
+	ld_library_dirs_done = 1;
+    }
 
-	    if (ld_library_dirs == NULL)
-		err(-1, "realloc() failed");
+    /* Do we need to grow? */
+    if (ld_library_dirlen == ld_library_dircount) {
+	ld_library_dirlen *= 2;
+	ld_library_dirs = realloc(ld_library_dirs,
+	    ld_library_dirlen * sizeof(int));
+	if (ld_library_dirs == NULL) {
+	    _rtld_error("add_libdir_fd: realloc failed");
+	    die();
 	}
+    }
 
-	ld_library_dirs[i] = fd;
+    /* Add the new library directory fd to the end. */
+    ld_library_dirs[ld_library_dircount] = fd;
+    ld_library_dircount++;
 }
 
 /*
- * Add file descriptors for a path list (e.g. '/lib:/usr/lib') to ld_library_dirs.
+ * Add file descriptors for a path list (e.g. '/lib:/usr/lib') to
+ * ld_library_dirs.
  */
 static void
-add_libdir_paths(const char *path) {
+add_libdir_paths(const char *path)
+{
 
     if (path == NULL)
 	return;
@@ -2161,24 +2169,22 @@ add_libdir_paths(const char *path) {
     strncpy(pathcopy, path, pathlen + 1);
 
     for (dirname = strtok_r(pathcopy, ":", &tokcontext); dirname;
-         dirname = strtok_r(NULL, ":", &tokcontext)) {
-
+	dirname = strtok_r(NULL, ":", &tokcontext)) {
+	struct try_library_args arg;
 	int fd;
 
-	struct try_library_args arg;
 	arg.name = "";
 	arg.namelen = 0;
 	arg.buffer = xmalloc(PATH_MAX);
 	arg.buflen = PATH_MAX;
 
-	if (try_library_path(dirname, strnlen(dirname, PATH_MAX), &arg))
+	if (try_library_path(dirname, strnlen(dirname, PATH_MAX), &arg)) {
 	    fd = open(dirname, O_RDONLY);
-
-	else {
+	} else {
 	    /* 'dirname' is not a directory path; perhaps it's a descriptor? */
 	    fd = (int) strtol(dirname, NULL, 0);
 	    if ((fd == 0) && (errno == 0))
-		    continue;
+		continue;
 	}
 
 	if (fd >= 0)
@@ -2192,57 +2198,47 @@ add_libdir_paths(const char *path) {
  * Build the list of library file descriptors.
  */
 static void
-init_libdirs(void) {
+init_libdirs(void)
+{
 #ifdef IN_RTLD_CAP
-
     char *envvar = getenv(LD_ "LIBRARY_DIRS");
+
     if (envvar == NULL)
 	err(-1, "No %s set in capability mode", LD_ "LIBRARY_DIRS");
 
     add_libdir_paths(envvar);
-
 #else /* !IN_RTLD_CAP */
-
     /* Look for directories a la find_library (TODO: refactor!). */
     add_libdir_paths(ld_library_path);
     add_libdir_paths(gethints());
     add_libdir_paths(STANDARD_LIBRARY_PATH);
 #endif
-
-    /* If all else fails, create an empty array */
-    if (ld_library_dirlen == 0) {
-	ld_library_dirs = malloc(sizeof(int));
-	ld_library_dirs[0] = -1;
-    }
 }
+
 /*
  * Return an array of file descriptors for the library search paths.
+ *
+ * XXX: synchronization of ld_library_dirs?
  */
 int
-ld_libdirs(int *fds, int *fdcount) {
-
-	if (fdcount == NULL)
-	    return (-1);
-
-	else if (fds == NULL) {
-	    *fdcount = -1;
-	    return (-1);
-	}
-
-	if (ld_library_dirs == NULL)
-	    init_libdirs();
-
-	int i = 0;
-	for (i = 0; (i < ld_library_dirlen) && (ld_library_dirs[i] != -1); i++) ;
-
-	if (*fdcount < i) {
-		*fdcount = i;
-		return (-1);
-	}
+ld_libdirs(int *fds, int *fdcount)
+{
 
-	*fdcount = i;
-	memcpy(fds, ld_library_dirs, i * sizeof(int));
-	return 0;
+    if (fdcount == NULL)
+	return (-1);
+    else if (fds == NULL) {
+	*fdcount = -1;
+	return (-1);
+    }
+    if (!ld_library_dirs_done)
+	init_libdirs();
+    if (*fdcount < ld_library_dircount) {
+	*fdcount = ld_library_dircount;
+	return (-1);
+    }
+    *fdcount = ld_library_dircount;
+    memcpy(fds, ld_library_dirs, ld_library_dircount * sizeof(int));
+    return (0);
 }
 
 int



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