this adds a -p option to ldconfig so you can do something like:

ldconfig -p /usr/local/lib/libsafe.so

to set a preload, and:

ldconfig -pm /usr/local/lib/libsafe.so

to merge one.

the major problem i know of with this patch is that setting a preload ELF
library will hose your ability to run linux binaries.

also, you probably need to:

cp /usr/src/include/elf-hints.h /usr/include/elf-hints.h

initially in order to build (is this indicative of larger build issues
involved with installed include files being selected before the one in the
source tree?)

--- include/elf-hints.h~        Fri Nov 30 23:10:12 2001
+++ include/elf-hints.h Fri Nov 30 23:11:15 2001
@@ -40,7 +40,10 @@
        u_int32_t       dirlist;        /* Offset of directory list in
                                           string table */
        u_int32_t       dirlistlen;     /* strlen(dirlist) */
-       u_int32_t       spare[26];      /* Room for expansion */
+       u_int32_t       preloadlist;    /* Offset of preload list in 
+                                          string table */
+       u_int32_t       preloadlistlen; /* strlen(preloadlist) */
+       u_int32_t       spare[24];      /* Room for expansion */
 };
 
 #define ELFHINTS_MAGIC 0x746e6845
--- libexec/rtld-elf/rtld.c~    Fri Nov 30 23:10:54 2001
+++ libexec/rtld-elf/rtld.c     Fri Nov 30 23:11:02 2001
@@ -52,8 +52,10 @@
 #include "debug.h"
 #include "rtld.h"
 
-#define END_SYM                "_end"
-#define PATH_RTLD      "/usr/libexec/ld-elf.so.1"
+#define END_SYM                        "_end"
+#define PATH_RTLD              "/usr/libexec/ld-elf.so.1"
+#define HINT_LIBRARY_PATH      0x01
+#define HINT_PRELOAD           0x02
 
 /* Types. */
 typedef void (*func_ptr_type)();
@@ -80,7 +82,7 @@
 static void errmsg_restore(char *);
 static char *errmsg_save(void);
 static char *find_library(const char *, const Obj_Entry *);
-static const char *gethints(void);
+static char *gethints(int);
 static void init_dag(Obj_Entry *);
 static void init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *);
 static void init_rtld(caddr_t);
@@ -91,7 +93,7 @@
 static void linkmap_add(Obj_Entry *);
 static void linkmap_delete(Obj_Entry *);
 static int load_needed_objects(Obj_Entry *);
-static int load_preload_objects(void);
+static int load_preload_objects(char *);
 static Obj_Entry *load_object(char *);
 static void lock_check(void);
 static Obj_Entry *obj_from_addr(const void *);
@@ -359,7 +361,9 @@
     sym_zero.st_shndx = SHN_ABS;
 
     dbg("loading LD_PRELOAD libraries");
-    if (load_preload_objects() == -1)
+    if (load_preload_objects(ld_preload) == -1)
+       die();
+    if (load_preload_objects(gethints(HINT_PRELOAD)) == -1)
        die();
     preload_tail = obj_tail;
 
@@ -805,7 +809,7 @@
     if ((refobj != NULL &&
       (pathname = search_library_path(name, refobj->rpath)) != NULL) ||
       (pathname = search_library_path(name, ld_library_path)) != NULL ||
-      (pathname = search_library_path(name, gethints())) != NULL ||
+      (pathname = search_library_path(name, gethints(HINT_LIBRARY_PATH))) != NULL ||
       (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
        return pathname;
 
@@ -873,38 +877,54 @@
  * necessary.  Returns NULL if there are problems with the hints file,
  * or if the search path there is empty.
  */
-static const char *
-gethints(void)
+static char *
+gethints(int hintflag)
 {
-    static char *hints;
+    static char *preload;
+    static char *library_path;
 
-    if (hints == NULL) {
+    if ((library_path == NULL) || (preload == NULL)) {
        int fd;
        struct elfhints_hdr hdr;
        char *p;
 
        /* Keep from trying again in case the hints file is bad. */
-       hints = "";
+       library_path = "";
+       preload = "";
 
        if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1)
            return NULL;
        if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
          hdr.magic != ELFHINTS_MAGIC ||
          hdr.version != 1) {
-           close(fd);
-           return NULL;
+           goto cleanup;
        }
        p = xmalloc(hdr.dirlistlen + 1);
        if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
          read(fd, p, hdr.dirlistlen + 1) != hdr.dirlistlen + 1) {
            free(p);
-           close(fd);
-           return NULL;
+           goto cleanup;
        }
-       hints = p;
+       library_path = p;
+       p = xmalloc(hdr.preloadlistlen + 1);
+       if (hdr.preloadlistlen == 0 ||
+         lseek(fd, hdr.strtab + hdr.preloadlist, SEEK_SET) == -1 ||
+         read(fd, p, hdr.preloadlistlen + 1) != hdr.preloadlistlen + 1) {
+           free(p);
+           goto cleanup;
+       }
+       preload = p;
+cleanup:
        close(fd);
     }
-    return hints[0] != '\0' ? hints : NULL;
+    switch (hintflag) {
+       case HINT_LIBRARY_PATH:
+          return library_path[0] != '\0' ? library_path : NULL;
+       case HINT_PRELOAD:
+          return preload[0] != '\0' ? preload : NULL;
+       default:
+         return NULL;
+    }
 }
 
 static void
@@ -1077,9 +1097,8 @@
 }
 
 static int
-load_preload_objects(void)
+load_preload_objects(char *p)
 {
-    char *p = ld_preload;
     static const char delim[] = " \t:;";
 
     if (p == NULL)
--- sbin/ldconfig/ldconfig.c~   Fri Nov 30 23:10:29 2001
+++ sbin/ldconfig/ldconfig.c    Fri Nov 30 23:11:33 2001
@@ -71,6 +71,7 @@
 static int                     justread;
 static int                     merge;
 static int                     rescan;
+static int                     preload;
 static char                    *hints_file;
 
 struct shlib_list {
@@ -117,7 +118,7 @@
        hints_file = is_aout ? _PATH_LD_HINTS : _PATH_ELF_HINTS;
        if (argc == 1)
                rescan = 1;
-       else while((c = getopt(argc, argv, "Rf:imrsv")) != -1) {
+       else while((c = getopt(argc, argv, "Rf:imrsvp")) != -1) {
                switch (c) {
                case 'R':
                        rescan = 1;
@@ -140,6 +141,9 @@
                case 'v':
                        verbose = 1;
                        break;
+               case 'p':
+                       preload = 1;
+                       break;
                default:
                        usage();
                        break;
@@ -150,8 +154,12 @@
                if (justread)
                        list_elf_hints(hints_file);
                else
-                       update_elf_hints(hints_file, argc - optind,
-                           argv + optind, merge || rescan);
+                       if (preload)
+                               update_elf_preloads(hints_file, argc - optind,
+                                   argv + optind, merge || rescan);
+                       else
+                               update_elf_dirs(hints_file, argc - optind,
+                                   argv + optind, merge || rescan);
                return 0;
        }
 
--- sbin/ldconfig/ldconfig.h~   Fri Nov 30 23:10:25 2001
+++ sbin/ldconfig/ldconfig.h    Fri Nov 30 23:11:33 2001
@@ -35,7 +35,8 @@
 
 __BEGIN_DECLS
 void   list_elf_hints __P((const char *));
-void   update_elf_hints __P((const char *, int, char **, int));
+void   update_elf_dirs __P((const char *, int, char **, int));
+void   update_elf_preloads __P((const char *, int, char **, int));
 __END_DECLS
 
 #endif
--- sbin/ldconfig/elfhints.c~   Fri Nov 30 23:10:36 2001
+++ sbin/ldconfig/elfhints.c    Fri Nov 30 23:54:52 2001
@@ -44,18 +44,56 @@
 #include "ldconfig.h"
 
 #define MAXDIRS                1024            /* Maximum directories in path */
+#define MAXPRELOADS    1024            /* Maximum preloaded libraries */
 #define MAXFILESIZE    (16*1024)       /* Maximum hints file size */
 
 static void    add_dir(const char *, const char *, int);
+static void    add_preload(const char *, const char *, int);
 static void    read_dirs_from_file(const char *, const char *);
 static void    read_elf_hints(const char *, int);
 static void    write_elf_hints(const char *);
 
 static const char      *dirs[MAXDIRS];
+static const char      *preloads[MAXPRELOADS];
 static int              ndirs;
+static int              npreloads;
 int                     insecure;
 
 static void
+add_preload(const char *hintsfile, const char *name, int trusted)
+{
+       struct stat     stbuf;
+       int             i;
+
+       if (!trusted && !insecure) {
+               if (stat(name, &stbuf) == -1) {
+                       warn("%s", name);
+                       return;
+               }
+               if (stbuf.st_uid != 0) {
+                       warnx("%s: ignoring library not owned by root", name);
+                       return;
+               }
+               if ((stbuf.st_mode & S_IWOTH) != 0) {
+                       warnx("%s: ignoring world-writable library", name);
+                       return;
+               }
+               if ((stbuf.st_mode & S_IWGRP) != 0) {
+                       warnx("%s: ignoring group-writable directory", name);
+                       return;
+               }
+       }
+
+       for (i = 0;  i < npreloads; i++)
+               if (strcmp(preloads[i], name) == 0)
+                       return;
+       if (npreloads >= MAXPRELOADS)
+               errx(1, "\"%s\": Too many preloaded libraries", hintsfile);
+       preloads[npreloads++] = name;
+}
+
+
+static void
 add_dir(const char *hintsfile, const char *name, int trusted)
 {
        struct stat     stbuf;
@@ -97,6 +135,10 @@
 
        read_elf_hints(hintsfile, 1);
        printf("%s:\n", hintsfile);
+       printf("\tpreloaded libraries:");
+       for (i = 0;  i < npreloads;  i++)
+               printf("%c%s", i == 0 ? ' ' : ':', preloads[i]);
+       printf("\n");
        printf("\tsearch directories:");
        for (i = 0;  i < ndirs;  i++)
                printf("%c%s", i == 0 ? ' ' : ':', dirs[i]);
@@ -192,6 +234,7 @@
        struct elfhints_hdr     *hdr;
        char                    *strtab;
        char                    *dirlist;
+       char                    *preloadlist;
        char                    *p;
 
        if ((fd = open(hintsfile, O_RDONLY)) == -1) {
@@ -222,19 +265,47 @@
 
        strtab = (char *)mapbase + hdr->strtab;
        dirlist = strtab + hdr->dirlist;
+       preloadlist = strtab + hdr->preloadlist;
 
        if (*dirlist != '\0')
                while ((p = strsep(&dirlist, ":")) != NULL)
                        add_dir(hintsfile, p, 1);
+printf("%d dirs loaded\n", ndirs);
+       if (*preloadlist != '\0' && hdr->preloadlistlen != 0)
+               while ((p = strsep(&preloadlist, ":")) != NULL)
+                       add_preload(hintsfile, p, 1);
+printf("%d preloads loaded\n", npreloads);
 }
 
 void
-update_elf_hints(const char *hintsfile, int argc, char **argv, int merge)
+update_elf_preloads(const char *hintsfile, int argc, char **argv, int merge)
 {
        int     i;
 
-       if (merge)
-               read_elf_hints(hintsfile, 0);
+       read_elf_hints(hintsfile, 0);
+       if (!merge)
+               npreloads = 0;
+       for (i = 0;  i < argc;  i++) {
+               struct stat     s;
+
+               if (stat(argv[i], &s) == -1)
+                       warn("warning: %s", argv[i]);
+               else if (!S_ISREG(s.st_mode))
+                       warn("not a regular file: %s", argv[i]);
+               else
+                       add_preload(hintsfile, argv[i], 0);
+       }
+       write_elf_hints(hintsfile);
+}
+
+void
+update_elf_dirs(const char *hintsfile, int argc, char **argv, int merge)
+{
+       int     i;
+printf("update_elf_dirs\n");   
+       read_elf_hints(hintsfile, 0);
+       if (!merge)
+               ndirs = 0;
        for (i = 0;  i < argc;  i++) {
                struct stat     s;
 
@@ -271,6 +342,8 @@
        hdr.strtab = sizeof hdr;
        hdr.strsize = 0;
        hdr.dirlist = 0;
+       hdr.preloadlistlen = 0;
+
        memset(hdr.spare, 0, sizeof hdr.spare);
 
        /* Count up the size of the string table. */
@@ -281,6 +354,16 @@
        }
        hdr.dirlistlen = hdr.strsize;
        hdr.strsize++;  /* For the null terminator */
+       hdr.preloadlist = hdr.strsize;
+
+       if (npreloads > 0) {
+               hdr.preloadlistlen += strlen(preloads[0]);
+               for (i = 1;  i < npreloads;  i++)
+                       hdr.preloadlistlen += 1 + strlen(preloads[i]);
+       }
+
+       hdr.strsize += hdr.preloadlistlen;
+       hdr.strsize++;  /* For the null terminator */
 
        /* Write the header. */
        if (fwrite(&hdr, 1, sizeof hdr, fp) != sizeof hdr)
@@ -293,6 +376,17 @@
                        if (fprintf(fp, ":%s", dirs[i]) < 0)
                                err(1, "%s: write error", tempname);
        }
+       if (putc('\0', fp) == EOF)
+               err(1, "%s: write error", tempname);
+
+       if (npreloads > 0) {
+               if (fputs(preloads[0], fp) == EOF)
+                       err(1, "%s: write error", tempname);
+               for (i = 1;  i < npreloads;  i++)
+                       if (fprintf(fp, ":%s", preloads[i]) < 0)
+                               err(1, "%s: write error", tempname);
+       }
+
        if (putc('\0', fp) == EOF || fclose(fp) == EOF)
                err(1, "%s: write error", tempname);
 
--- sbin/ldconfig/ldconfig.8~   Sat Dec  1 00:05:20 2001
+++ sbin/ldconfig/ldconfig.8    Sat Dec  1 00:04:13 2001
@@ -38,7 +38,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl aout | Fl elf
-.Op Fl Rimrsv
+.Op Fl Rimrsvp
 .Op Fl f Ar hints_file
 .Op Ar directory | Ar
 .Sh DESCRIPTION
@@ -128,6 +128,8 @@
 for shared libraries.
 .It Fl v
 Switch on verbose mode.
+.It Fl p
+The arguments are taken to be libraries to globally preload.
 .El
 .Sh Security
 Special care must be taken when loading shared libraries into the address

Reply via email to