From owner-p4-projects@FreeBSD.ORG Sun Jun 7 19:47:15 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2F69E1065677; Sun, 7 Jun 2009 19:47:15 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id E26B21065675 for ; Sun, 7 Jun 2009 19:47:14 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id CE5E58FC14 for ; Sun, 7 Jun 2009 19:47:14 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n57JlEP2076393 for ; Sun, 7 Jun 2009 19:47:14 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n57JlEvc076391 for perforce@freebsd.org; Sun, 7 Jun 2009 19:47:14 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Sun, 7 Jun 2009 19:47:14 GMT Message-Id: <200906071947.n57JlEvc076391@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson To: Perforce Change Reviews Cc: Subject: PERFORCE change 163727 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Jun 2009 19:47:15 -0000 http://perforce.freebsd.org/chv.cgi?CH=163727 Change 163727 by rwatson@rwatson_freebsd_capabilities on 2009/06/07 19:46:46 Rework ifdef'ing of rtld-elf/rtld-elf-cap so that less unnecessary code is compiled in in the capability-mode case, avoiding unnecessary security exceptions as rtld tries to analyze and search library paths. Add caplibindex, a facility to pass shared libraries into capability-mode executables as file descriptors, with an environmental variable that maps file descriptors to library names. This allows callers to pre-populate the sandboxed rtld environment with the libraries a binary needs to run (such as libc). Always validate MNT_NOEXEC for libraries passed in this way, as this is the moral equivalent of LD_LIBRARY_PATH. Affected files ... .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/Makefile#15 edit .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/rtld_caplibindex.c#1 add .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/rtld_caplibindex.h#1 add .. //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/rtld.c#14 edit Differences ... ==== //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/Makefile#15 (text+ko) ==== @@ -1,5 +1,5 @@ # $FreeBSD$ -# $P4: //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/Makefile#14 $ +# $P4: //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf-cap/Makefile#15 $ WITHOUT_SSP= @@ -9,11 +9,11 @@ SRCS= rtld_start.S \ reloc.c rtld.c rtld_lock.c map_object.c \ malloc.c xmalloc.c debug.c \ - crtbrand.c + crtbrand.c rtld_caplibindex.c MAN= rtld-elf-cap.1 CSTD?= gnu99 CFLAGS+= -Wall -DFREEBSD_ELF -DIN_RTLD -DIN_RTLD_CAP -g -CFLAGS+= -I${.CURDIR}/../rtld-elf/${MACHINE_ARCH} -I${.CURDIR}/../rtld-elf +CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../rtld-elf/${MACHINE_ARCH} -I${.CURDIR}/../rtld-elf LDFLAGS+= -nostdlib -Wl,-e,.rtld_start -Wl,-T,${.CURDIR}/rtld-elf-cap.xs INSTALLFLAGS= -C -b PRECIOUSPROG= ==== //depot/projects/trustedbsd/capabilities/src/libexec/rtld-elf/rtld.c#14 (text+ko) ==== @@ -59,6 +59,10 @@ #include "libmap.h" #include "rtld_tls.h" +#ifdef IN_RTLD_CAP +#include "rtld_caplibindex.h" +#endif + #ifndef COMPAT_32BIT #ifdef IN_RTLD_CAP #define PATH_RTLD "/libexec/ld-elf-cap.so.1" @@ -114,7 +118,9 @@ static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); static int load_needed_objects(Obj_Entry *); +#ifndef IN_RTLD_CAP static int load_preload_objects(void); +#endif static Obj_Entry *load_object(const char *, const Obj_Entry *); static Obj_Entry *obj_from_addr(const void *); static void objlist_call_fini(Objlist *, int *lockstate); @@ -175,12 +181,17 @@ used to affect the libraries loaded */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ +#ifndef IN_RTLD_CAP static char *ld_library_path; /* Environment variable for search path */ static char *ld_preload; /* Environment variable for libraries to load first */ static char *ld_elf_hints_path; /* Environment variable for alternative hints path */ +#endif static char *ld_tracing; /* Called from ldd to print libs */ static char *ld_utrace; /* Use utrace() to log events. */ +#ifdef IN_RTLD_CAP +static char *ld_caplibindex; +#endif static Obj_Entry *obj_list; /* Head of linked list of shared objects */ static Obj_Entry **obj_tail; /* Link field of last object in list */ static Obj_Entry *obj_main; /* The main program shared object */ @@ -341,9 +352,11 @@ const char *argv0; Objlist_Entry *entry; Obj_Entry *obj; +#ifndef IN_RTLD_CAP Obj_Entry **preload_tail; Objlist initlist; int lockstate; +#endif /* * On entry, the dynamic linker itself has not been relocated yet. @@ -409,32 +422,45 @@ * future processes to honor the potentially un-safe variables. */ if (!trust) { +#ifndef IN_RTLD_CAP unsetenv(LD_ "PRELOAD"); unsetenv(LD_ "LIBMAP"); unsetenv(LD_ "LIBRARY_PATH"); unsetenv(LD_ "LIBMAP_DISABLE"); +#endif unsetenv(LD_ "DEBUG"); +#ifndef IN_RTLD_CAP unsetenv(LD_ "ELF_HINTS_PATH"); +#endif +#ifdef IN_RTLD_CAP + unsetenv(LD_ "CAPLIBINDEX"); +#endif } ld_debug = getenv(LD_ "DEBUG"); -#ifndef IN_RTLD_CAP +#ifdef IN_RTLD_CAP + ld_caplibindex = getenv(LD_ "CAPLIBINDEX"); +#else libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; libmap_override = getenv(LD_ "LIBMAP"); -#endif ld_library_path = getenv(LD_ "LIBRARY_PATH"); ld_preload = getenv(LD_ "PRELOAD"); ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); +#endif dangerous_ld_env = -#ifndef IN_RTLD_CAP +#ifdef IN_RTLD_CAP + 1; +#else libmap_disable || (libmap_override != NULL) || -#endif (ld_library_path != NULL) || (ld_preload != NULL) || (ld_elf_hints_path != NULL); +#endif ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); ld_utrace = getenv(LD_ "UTRACE"); +#ifndef IN_RTLD_CAP if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) ld_elf_hints_path = _PATH_ELF_HINTS; +#endif if (ld_debug != NULL && *ld_debug != '\0') debug = 1; @@ -523,15 +549,20 @@ sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym_zero.st_shndx = SHN_UNDEF; +#ifdef IN_RTLD_CAP + if (ld_caplibindex != NULL) + ld_caplibindex_init(ld_caplibindex); +#endif + #ifndef IN_RTLD_CAP if (!libmap_disable) libmap_disable = (bool)lm_init(libmap_override); -#endif dbg("loading LD_PRELOAD libraries"); if (load_preload_objects() == -1) die(); preload_tail = obj_tail; +#endif dbg("loading needed objects"); if (load_needed_objects(obj_main) == -1) @@ -588,16 +619,20 @@ dbg("initializing thread locks"); lockdflt_init(); +#ifndef IN_RTLD_CAP /* Make a list of init functions to call. */ objlist_init(&initlist); initlist_add_objects(obj_list, preload_tail, &initlist); +#endif r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ +#ifndef IN_RTLD_CAP lockstate = wlock_acquire(rtld_bind_lock); objlist_call_init(&initlist, &lockstate); objlist_clear(&initlist); wlock_release(rtld_bind_lock, lockstate); +#endif dbg("transferring control to program entry point = %p", obj_main->entry); @@ -1499,6 +1534,7 @@ return 0; } +#ifndef IN_RTLD_CAP static int load_preload_objects(void) { @@ -1524,6 +1560,7 @@ LD_UTRACE(UTRACE_PRELOAD_FINISHED, NULL, NULL, 0, 0, NULL); return 0; } +#endif /* * Load a shared object into memory, if it is not already loaded. @@ -1549,11 +1586,18 @@ return NULL; } path = xstrdup(name); + if (ld_caplibindex_lookup(path, &fd) < 0) { + _rtld_error("Unable to find \"%s\" in LD_CAPLIBINDEX", path); + return NULL; + } + if (lseek(fd, 0, SEEK_SET) == -1) { + _rtld_error("Unable to seek on \"%s\"", path); + return NULL; + } #else path = find_library(name, refobj); if (path == NULL) return NULL; -#endif /* * If we didn't find a match by pathname, open the file and check @@ -1568,22 +1612,29 @@ free(path); return NULL; } +#endif if (fstat(fd, &sb) == -1) { _rtld_error("Cannot fstat \"%s\"", path); +#ifndef IN_RTLD_CAP close(fd); +#endif free(path); return NULL; } for (obj = obj_list->next; obj != NULL; obj = obj->next) { if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) { +#ifndef IN_RTLD_CAP close(fd); +#endif break; } } if (obj != NULL) { object_add_name(obj, name); free(path); +#ifndef IN_RTLD_CAP close(fd); +#endif return obj; } @@ -1591,7 +1642,9 @@ obj = do_load_object(fd, name, path, &sb); if (obj == NULL) free(path); +#ifndef IN_RTLD_CAP close(fd); +#endif return obj; }