make the dynamic linker find its path file relative to its own location
authorRich Felker <dalias@aerifal.cx>
Thu, 18 Jul 2013 23:29:44 +0000 (19:29 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 18 Jul 2013 23:29:44 +0000 (19:29 -0400)
prior to this change, using a non-default syslibdir was impractical on
systems where the ordinary library paths contain musl-incompatible
library files. the file containing search paths was always taken from
/etc, which would either correspond to a system-wide musl
installation, or fail to exist at all, resulting in searching of the
default library path.

the new search strategy is safe even for suid programs because the
pathname used comes from the PT_INTERP header of the program being
run, rather than any external input.

as part of this change, I have also begun differentiating the names of
arch variants that differ by endianness or floating point calling
convention. the corresponding changes in the build system and and gcc
wrapper script (to use an alternate dynamic linker name) for these
configurations have not yet been made.

arch/arm/reloc.h
arch/i386/reloc.h
arch/microblaze/reloc.h
arch/mips/reloc.h
arch/powerpc/reloc.h
arch/x86_64/reloc.h
src/ldso/dynlink.c

index b41314de8bd8c55eadcb09585ba1ae8d0ff97120..9ca0b48ce3d4f4761edec470f8fee28a05a35d9f 100644 (file)
@@ -1,7 +1,20 @@
 #include <string.h>
 #include <elf.h>
+#include <endian.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-arm.path"
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ENDIAN_SUFFIX "eb"
+#else
+#define ENDIAN_SUFFIX ""
+#endif
+
+#if __SOFTFP__
+#define FP_SUFFIX ""
+#else
+#define FP_SUFFIX "hf"
+#endif
+
+#define LDSO_ARCH "arm" ENDIAN_SUFFIX FP_SUFFIX
 
 #define IS_COPY(x) ((x)==R_ARM_COPY)
 #define IS_PLT(x) ((x)==R_ARM_JUMP_SLOT)
index da0bc05dc72c4f00087e5e0c2d65c2741efd87f9..3923b54b100b013665d71d57b25fcf7f3d1a92e8 100644 (file)
@@ -1,7 +1,7 @@
 #include <string.h>
 #include <elf.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-i386.path"
+#define LDSO_ARCH "i386"
 
 #define IS_COPY(x) ((x)==R_386_COPY)
 #define IS_PLT(x) ((x)==R_386_JMP_SLOT)
index 81add5e92232958dd0e06e09019d79e7cad82ca3..60f742251bd79ebc4eeb1f4593ece671f69f4c78 100644 (file)
@@ -1,7 +1,14 @@
 #include <string.h>
 #include <elf.h>
+#include <endian.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-microblaze.path"
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ENDIAN_SUFFIX "el"
+#else
+#define ENDIAN_SUFFIX ""
+#endif
+
+#define LDSO_ARCH "microblaze" ENDIAN_SUFFIX
 
 #define IS_COPY(x) ((x)==R_MICROBLAZE_COPY)
 #define IS_PLT(x) ((x)==R_MICROBLAZE_JUMP_SLOT)
index f5e9c77b0c63f4e9754b8fee95661d71c87e4b67..4c035f3276cc97f540b928b0da353851b5fa4347 100644 (file)
@@ -1,7 +1,14 @@
 #include <string.h>
 #include <elf.h>
+#include <endian.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-mips.path"
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define ENDIAN_SUFFIX "el"
+#else
+#define ENDIAN_SUFFIX ""
+#endif
+
+#define LDSO_ARCH "mips" ENDIAN_SUFFIX
 
 #define IS_COPY(x) ((x)==R_MIPS_COPY)
 #define IS_PLT(x) 1
index 113dfa151e113f4dbf870e0073d57a0ab63cc103..80b9ebc9812bd53e5b1c2f0546d7d7d165d9da09 100644 (file)
@@ -1,7 +1,7 @@
 #include <string.h>
 #include <elf.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-powerpc.path"
+#define LDSO_ARCH "powerpc" ENDIAN_SUFFIX
 
 #define IS_COPY(x) ((x)==R_PPC_COPY)
 #define IS_PLT(x) ((x)==R_PPC_JMP_SLOT)
index 38a60735593d9141497d6387c4df149077568f26..28cf7cc1563fe1e377e4d53e7bd4416e7f8948ea 100644 (file)
@@ -2,7 +2,7 @@
 #include <string.h>
 #include <elf.h>
 
-#define ETC_LDSO_PATH "/etc/ld-musl-x86_64.path"
+#define LDSO_ARCH "x86_64"
 
 #define IS_COPY(x) ((x)==R_X86_64_COPY)
 #define IS_PLT(x) ((x)==R_X86_64_JUMP_SLOT)
index ff5b738d7633a11548e315ec12ea7b0a81cffcee..1d5e2977825e612540886a636e3343b10031a8a9 100644 (file)
@@ -483,7 +483,26 @@ static struct dso *load_library(const char *name)
                if (fd < 0 && env_path) fd = path_open(name, env_path, buf, sizeof buf);
                if (fd < 0) {
                        if (!sys_path) {
-                               FILE *f = fopen(ETC_LDSO_PATH, "rbe");
+                               char *prefix = 0;
+                               size_t prefix_len;
+                               if (ldso->name[0]=='/') {
+                                       char *s, *t, *z;
+                                       for (s=t=z=ldso->name; *s; s++)
+                                               if (*s=='/') z=t, t=s;
+                                       prefix_len = z-ldso->name;
+                                       if (prefix_len < PATH_MAX)
+                                               prefix = ldso->name;
+                               }
+                               if (!prefix) {
+                                       prefix = "";
+                                       prefix_len = 0;
+                               }
+                               char etc_ldso_path[prefix_len + 1
+                                       + sizeof "/etc/ld-musl-" LDSO_ARCH ".path"];
+                               snprintf(etc_ldso_path, sizeof etc_ldso_path,
+                                       "%.*s/etc/ld-musl-" LDSO_ARCH ".path",
+                                       (int)prefix_len, prefix);
+                               FILE *f = fopen(etc_ldso_path, "rbe");
                                if (f) {
                                        if (getdelim(&sys_path, (size_t[1]){0}, 0, f) <= 0) {
                                                free(sys_path);