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