diff -urN libexec/rtld-elf.old/Makefile libexec/rtld-elf/Makefile --- libexec/rtld-elf.old/Makefile Sun Jun 23 06:32:35 2002 +++ libexec/rtld-elf/Makefile Wed Oct 8 02:50:10 2003 @@ -2,7 +2,7 @@ PROG= ld-elf.so.1 SRCS= rtld_start.S rtld.c lockdflt.c map_object.c malloc.c \ - xmalloc.c debug.c reloc.c + xmalloc.c debug.c reloc.c libmap.c MAN= rtld.1 CFLAGS+= -Wall -DFREEBSD_ELF -I${.CURDIR}/${MACHINE_ARCH} -I${.CURDIR} LDFLAGS+= -nostdlib -e .rtld_start diff -urN libexec/rtld-elf.old/libmap.c libexec/rtld-elf/libmap.c --- libexec/rtld-elf.old/libmap.c Thu Jan 1 09:00:00 1970 +++ libexec/rtld-elf/libmap.c Wed Oct 8 02:44:17 2003 @@ -0,0 +1,255 @@ +/* + * $FreeBSD: src/libexec/rtld-elf/libmap.c,v 1.9 2003/09/13 21:43:08 mdodd Exp $ + */ + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "rtld.h" +#include "libmap.h" + +#ifndef _PATH_LIBMAP_CONF +#define _PATH_LIBMAP_CONF "/etc/libmap.conf" +#endif + +TAILQ_HEAD(lm_list, lm); +struct lm { + char *f; + char *t; + + TAILQ_ENTRY(lm) lm_link; +}; + +TAILQ_HEAD(lmp_list, lmp) lmp_head = TAILQ_HEAD_INITIALIZER(lmp_head); +struct lmp { + char *p; + struct lm_list lml; + TAILQ_ENTRY(lmp) lmp_link; +}; + +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 *); + +#define iseol(c) (((c) == '#') || ((c) == '\0') || \ + ((c) == '\n') || ((c) == '\r')) + +int +lm_init (void) +{ + FILE *fp; + char *cp; + char *f, *t, *p, *c; + char prog[MAXPATHLEN]; + char line[MAXPATHLEN + 2]; + + dbg("%s()", __func__); + + TAILQ_INIT(&lmp_head); + + if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL) + return (1); + + p = NULL; + while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) { + t = f = c = NULL; + + /* Skip over leading space */ + while (isspace(*cp)) cp++; + + /* Found a comment or EOL */ + if (iseol(*cp)) continue; + + /* Found a constraint selector */ + if (*cp == '[') { + cp++; + + /* Skip leading space */ + while (isspace(*cp)) cp++; + + /* Found comment, EOL or end of selector */ + if (iseol(*cp) || *cp == ']') + continue; + + c = cp++; + /* Skip to end of word */ + while (!isspace(*cp) && !iseol(*cp) && *cp != ']') + cp++; + + /* Skip and zero out trailing space */ + while (isspace(*cp)) *cp++ = '\0'; + + /* Check if there is a closing brace */ + if (*cp != ']') continue; + + /* Terminate string if there was no trailing space */ + *cp++ = '\0'; + + /* + * There should be nothing except whitespace or comment + from this point to the end of the line. + */ + while(isspace(*cp)) *cp++; + if (!iseol(*cp)) continue; + + strcpy(prog, c); + p = prog; + continue; + } + + /* Parse the 'from' candidate. */ + f = cp++; + while (!isspace(*cp) && !iseol(*cp)) cp++; + + /* Skip and zero out the trailing whitespace */ + while (isspace(*cp)) *cp++ = '\0'; + + /* Found a comment or EOL */ + if (iseol(*cp)) continue; + + /* Parse 'to' mapping */ + t = cp++; + while (!isspace(*cp) && !iseol(*cp)) cp++; + + /* Skip and zero out the trailing whitespace */ + while (isspace(*cp)) *cp++ = '\0'; + + /* Should be no extra tokens at this point */ + if (!iseol(*cp)) continue; + + *cp = '\0'; + lm_add(p, f, t); + } + fclose(fp); + return (0); +} + +static void +lm_free (struct lm_list *lml) +{ + struct lm *lm; + + dbg("%s(%p)", __func__, lml); + + while (!TAILQ_EMPTY(lml)) { + lm = TAILQ_FIRST(lml); + TAILQ_REMOVE(lml, lm, lm_link); + free(lm->f); + free(lm->t); + free(lm); + } + return; +} + +void +lm_fini (void) +{ + struct lmp *lmp; + + dbg("%s()", __func__); + + while (!TAILQ_EMPTY(&lmp_head)) { + lmp = TAILQ_FIRST(&lmp_head); + TAILQ_REMOVE(&lmp_head, lmp, lmp_link); + free(lmp->p); + lm_free(&lmp->lml); + free(lmp); + } + return; +} + +static void +lm_add (const char *p, const char *f, const char *t) +{ + struct lm_list *lml; + struct lm *lm; + + if (p == NULL) + p = "$DEFAULT$"; + + dbg("%s(\"%s\", \"%s\", \"%s\")", __func__, p, f, t); + + if ((lml = lmp_find(p)) == NULL) + lml = lmp_init(xstrdup(p)); + + lm = xmalloc(sizeof(struct lm)); + lm->f = xstrdup(f); + lm->t = xstrdup(t); + TAILQ_INSERT_HEAD(lml, lm, lm_link); +} + +char * +lm_find (const char *p, const char *f) +{ + struct lm_list *lml; + char *t; + + dbg("%s(\"%s\", \"%s\")", __func__, p, f); + + if (p != NULL && (lml = lmp_find(p)) != NULL) { + t = lml_find(lml, f); + if (t != NULL) { + /* + * Add a global mapping if we have + * a successful constrained match. + */ + lm_add(NULL, f, t); + return (t); + } + } + lml = lmp_find("$DEFAULT$"); + if (lml != NULL) + return (lml_find(lml, f)); + else + return (NULL); +} + +static char * +lml_find (struct lm_list *lmh, const char *f) +{ + struct lm *lm; + + dbg("%s(%p, \"%s\")", __func__, lmh, f); + + TAILQ_FOREACH(lm, lmh, lm_link) + if ((strncmp(f, lm->f, strlen(lm->f)) == 0) && + (strlen(f) == strlen(lm->f))) + return (lm->t); + return NULL; +} + +static struct lm_list * +lmp_find (const char *n) +{ + struct lmp *lmp; + + dbg("%s(\"%s\")", __func__, n); + + TAILQ_FOREACH(lmp, &lmp_head, lmp_link) + if ((strncmp(n, lmp->p, strlen(lmp->p)) == 0) && + (strlen(n) == strlen(lmp->p))) + return (&lmp->lml); + return (NULL); +} + +static struct lm_list * +lmp_init (char *n) +{ + struct lmp *lmp; + + dbg("%s(\"%s\")", __func__, n); + + lmp = xmalloc(sizeof(struct lmp)); + lmp->p = n; + TAILQ_INIT(&lmp->lml); + TAILQ_INSERT_HEAD(&lmp_head, lmp, lmp_link); + + return (&lmp->lml); +} diff -urN libexec/rtld-elf.old/libmap.h libexec/rtld-elf/libmap.h --- libexec/rtld-elf.old/libmap.h Thu Jan 1 09:00:00 1970 +++ libexec/rtld-elf/libmap.h Wed Oct 8 02:44:17 2003 @@ -0,0 +1,7 @@ +/* + * $FreeBSD: src/libexec/rtld-elf/libmap.h,v 1.2 2003/09/13 21:43:08 mdodd Exp $ + */ + +int lm_init (void); +void lm_fini (void); +char * lm_find (const char *, const char *); diff -urN libexec/rtld-elf.old/rtld.1 libexec/rtld-elf/rtld.1 --- libexec/rtld-elf.old/rtld.1 Sat Jan 12 02:35:52 2002 +++ libexec/rtld-elf/rtld.1 Wed Oct 8 02:50:10 2003 @@ -88,6 +88,9 @@ other shared libraries. If the directory is not specified then the directories specified by +.It Ev LD_LIBMAP_DISABLE +If set, disables the use of +.Xr libmap.conf 5 . .Ev LD_LIBRARY_PATH will be searched first followed by the set of built-in standard directories. @@ -147,9 +150,12 @@ .Sh FILES .Bl -tag -width indent .It Pa /var/run/ld-elf.so.hints +.It Pa /etc/libmap.conf +The libmap configuration file. .El .Sh SEE ALSO .Xr ld 1 , .Xr ldd 1 , .Xr elf 5 , +.Xr libmap.conf 5 , .Xr ldconfig 8 diff -urN libexec/rtld-elf.old/rtld.c libexec/rtld-elf/rtld.c --- libexec/rtld-elf.old/rtld.c Sat Feb 22 00:50:43 2003 +++ libexec/rtld-elf/rtld.c Wed Oct 8 02:50:10 2003 @@ -52,6 +52,7 @@ #include "debug.h" #include "rtld.h" +#include "libmap.h" #define END_SYM "_end" #define PATH_RTLD "/usr/libexec/ld-elf.so.1" @@ -131,6 +132,7 @@ */ static char *error_message; /* Message for dlerror(), or NULL */ struct r_debug r_debug; /* for GDB; */ +static bool libmap_disable; /* Disable libmap */ 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 */ @@ -293,6 +295,7 @@ ld_bind_now = getenv("LD_BIND_NOW"); if (trust) { ld_debug = getenv("LD_DEBUG"); + libmap_disable = getenv("LD_LIBMAP_DISABLE") != NULL; ld_library_path = getenv("LD_LIBRARY_PATH"); ld_preload = getenv("LD_PRELOAD"); } @@ -366,6 +369,9 @@ sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym_zero.st_shndx = SHN_ABS; + if (!libmap_disable) + libmap_disable = (bool)lm_init(); + dbg("loading LD_PRELOAD libraries"); if (load_preload_objects() == -1) die(); @@ -791,19 +797,24 @@ * /usr/lib */ static char * -find_library(const char *name, const Obj_Entry *refobj) +find_library(const char *xname, const Obj_Entry *refobj) { char *pathname; + char *name; - if (strchr(name, '/') != NULL) { /* Hard coded pathname */ - if (name[0] != '/' && !trust) { + if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ + if (xname[0] != '/' && !trust) { _rtld_error("Absolute pathname required for shared object \"%s\"", - name); + xname); return NULL; } - return xstrdup(name); + return xstrdup(xname); } + if (libmap_disable || (refobj == NULL) || + (name = lm_find(refobj->path, xname)) == NULL) + name = (char *)xname; + dbg(" Searching for \"%s\"", name); if ((pathname = search_library_path(name, ld_library_path)) != NULL || @@ -1433,6 +1444,8 @@ obj->refcount = 0; objlist_call_fini(&list_fini); /* No need to remove the items from the list, since we are exiting. */ + if (!libmap_disable) + lm_fini(); } static void *