diff --git a/libexec/rtld-elf/libmap.c b/libexec/rtld-elf/libmap.c index d683fdb9b8fd..cb72f03f3176 100644 --- a/libexec/rtld-elf/libmap.c +++ b/libexec/rtld-elf/libmap.c @@ -38,32 +38,70 @@ struct lmp { TAILQ_ENTRY(lmp) lmp_link; }; +static int lm_count; + +static void lmc_parse (FILE *); static void lm_add (const char *, const char *, const char *); static void lm_free (struct lm_list *); static char * lml_find (struct lm_list *, const char *); static struct lm_list * lmp_find (const char *); static struct lm_list * lmp_init (char *); static const char * quickbasename (const char *); +static int readstrfn (void * cookie, char *buf, int len); +static int closestrfn (void * cookie); #define iseol(c) (((c) == '#') || ((c) == '\0') || \ ((c) == '\n') || ((c) == '\r')) int -lm_init (void) +lm_init (char *libmap_override) { FILE *fp; - char *cp; - char *f, *t, *p, *c; - char prog[MAXPATHLEN]; - char line[MAXPATHLEN + 2]; - dbg("%s()", __func__); + dbg("%s(\"%s\")", __func__, libmap_override); TAILQ_INIT(&lmp_head); - if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL) - return (1); + fp = fopen(_PATH_LIBMAP_CONF, "r"); + if (fp) { + lmc_parse(fp); + fclose(fp); + } + if (libmap_override) { + char *p; + /* do some character replacement to make $LIBMAP look like a + text file, then "open" it with funopen */ + libmap_override = xstrdup(libmap_override); + + for (p = libmap_override; *p; p++) { + switch (*p) { + case '=': + *p = ' '; break; + case ',': + *p = '\n'; break; + } + } + fp = funopen(libmap_override, readstrfn, NULL, NULL, closestrfn); + if (fp) { + lmc_parse(fp); + fclose(fp); + } + } + + return (lm_count == 0); +} + +static void +lmc_parse (FILE *fp) +{ + char *cp; + char *f, *t, *c, *p; + char prog[MAXPATHLEN]; + char line[MAXPATHLEN + 2]; + + dbg("%s(%p)", __func__, fp); + p = NULL; while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) { t = f = c = NULL; @@ -134,8 +172,6 @@ lm_init (void) *cp = '\0'; lm_add(p, f, t); } - fclose(fp); - return (0); } static void @@ -190,6 +226,7 @@ lm_add (const char *p, const char *f, const char *t) lm->f = xstrdup(f); lm->t = xstrdup(t); TAILQ_INSERT_HEAD(lml, lm, lm_link); + lm_count++; } char * @@ -304,3 +341,31 @@ quickbasename (const char *path) } return (p); } + +static int +readstrfn(void * cookie, char *buf, int len) +{ + static char *current; + static int left; + int copied; + + copied = 0; + if (!current) { + current = cookie; + left = strlen(cookie); + } + while (*current && left && len) { + *buf++ = *current++; + left--; + len--; + copied++; + } + return copied; +} + +static int +closestrfn(void * cookie) +{ + free(cookie); + return 0; +} diff --git a/libexec/rtld-elf/libmap.h b/libexec/rtld-elf/libmap.h index e4bd0aeb9bd1..53b2ba1ec0bf 100644 --- a/libexec/rtld-elf/libmap.h +++ b/libexec/rtld-elf/libmap.h @@ -2,7 +2,7 @@ * $FreeBSD$ */ -int lm_init (void); +int lm_init (char *); void lm_fini (void); char * lm_find (const char *, const char *); #ifdef COMPAT_32BIT diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 index a73bec30077e..17c007d3bfef 100644 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -93,9 +93,22 @@ If set .Nm will print a table containing all relocations before symbol binding and relocation. +.It Ev LD_LIBMAP +A library replacement list in the same format as +.Xr libmap.conf 5 . +For convenience, the characters +.Ql = +and +.Ql \&, +can be used instead of a space and a newline. +This variable is parsed after +.Xr libmap.conf 5 , +and will override its entries. .It Ev LD_LIBMAP_DISABLE If set, disables the use of -.Xr libmap.conf 5 . +.Xr libmap.conf 5 +and +.Ev LD_LIBMAP . .It Ev LD_LIBRARY_PATH A colon separated list of directories, overriding the default search path for shared libraries. diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 2741c1378979..6fc64dd7173b 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -137,6 +137,7 @@ void r_debug_state(struct r_debug*, struct link_map*); static char *error_message; /* Message for dlerror(), or NULL */ struct r_debug r_debug; /* for GDB; */ static bool libmap_disable; /* Disable libmap */ +static char *libmap_override; /* Maps to use in addition to libmap.conf */ static bool trust; /* False for setuid and setgid programs */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ @@ -289,6 +290,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) if (trust) { ld_debug = getenv(LD_ "DEBUG"); libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; + libmap_override = getenv(LD_ "LIBMAP"); ld_library_path = getenv(LD_ "LIBRARY_PATH"); ld_preload = getenv(LD_ "PRELOAD"); } @@ -363,7 +365,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) sym_zero.st_shndx = SHN_UNDEF; if (!libmap_disable) - libmap_disable = (bool)lm_init(); + libmap_disable = (bool)lm_init(libmap_override); dbg("loading LD_PRELOAD libraries"); if (load_preload_objects() == -1)