]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
build-path: fix SIGSEGV on RISC-V and MIPS
authorLuca Boccassi <bluca@debian.org>
Sat, 27 Apr 2024 14:25:09 +0000 (15:25 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 30 Apr 2024 16:11:10 +0000 (18:11 +0200)
On RISC-V and MIPS DT_STRTAB is an offset, not a full address.

Follow-up for 91d149cfb45fc2fad7ce18fb651297ee50ecc1f8

src/basic/build-path.c

index 8ddef7b2dd5e3cf97b61684a2e6a86981b85be78..b5972658dfea11101640a2b4c06db41eb6c3e00c 100644 (file)
@@ -12,7 +12,7 @@
 #include "process-util.h"
 #include "unistd.h"
 
-static int get_runpath_from_dynamic(const ElfW(Dyn) *d, const char **ret) {
+static int get_runpath_from_dynamic(const ElfW(Dyn) *d, ElfW(Addr) bias, const char **ret) {
         size_t runpath_index = SIZE_MAX, rpath_index = SIZE_MAX;
         const char *strtab = NULL;
 
@@ -33,7 +33,14 @@ static int get_runpath_from_dynamic(const ElfW(Dyn) *d, const char **ret) {
                         break;
 
                 case DT_STRTAB:
-                        strtab = (const char *) d->d_un.d_val;
+                        /* On MIPS and RISC-V DT_STRTAB records an offset, not a valid address, so it has to be adjusted
+                         * using the bias calculated earlier. */
+                        if (d->d_un.d_val != 0)
+                                strtab = (const char *) ((uintptr_t) d->d_un.d_val
+#if defined(__mips__) || defined(__riscv)
+                                         + bias
+#endif
+                                );
                         break;
                 }
 
@@ -45,7 +52,7 @@ static int get_runpath_from_dynamic(const ElfW(Dyn) *d, const char **ret) {
         if (!strtab)
                 return -ENOTRECOVERABLE;
 
-        /* According to dl.so runpath wins of both runpath and rpath are defined. */
+        /* According to ld.so runpath wins if both runpath and rpath are defined. */
         if (runpath_index != SIZE_MAX) {
                 if (ret)
                         *ret = strtab + runpath_index;
@@ -111,7 +118,7 @@ static int get_runpath(const char **ret) {
         if (!found_dyn)
                 return -ENOTRECOVERABLE;
 
-        return get_runpath_from_dynamic((const ElfW(Dyn)*) (bias + dyn), ret);
+        return get_runpath_from_dynamic((const ElfW(Dyn)*) (bias + dyn), bias, ret);
 }
 
 int get_build_exec_dir(char **ret) {