From: Paul Floyd Date: Thu, 6 Feb 2025 19:23:42 +0000 (+0100) Subject: Bug 396415 - Valgrind is not looking up $ORIGIN rpath of shebang programs X-Git-Tag: VALGRIND_3_25_0~155 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fefba79021779d840bbf8cebc43e40c74b40f31;p=thirdparty%2Fvalgrind.git Bug 396415 - Valgrind is not looking up $ORIGIN rpath of shebang programs --- diff --git a/NEWS b/NEWS index ca5bfb23f4..1c627c7744 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,7 @@ bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather than mailing the developers (or mailing lists) directly -- bugs that are not entered into bugzilla tend to get forgotten about or ignored. +396415 Valgrind is not looking up $ORIGIN rpath of shebang programs 487296 --track-fds=yes and --track-fds=all report erroneous information when fds 0, 1, or 2 are used as non-std 489913 WARNING: unhandled amd64-linux syscall: 444 (landlock_create_ruleset) diff --git a/coregrind/m_initimg/initimg-darwin.c b/coregrind/m_initimg/initimg-darwin.c index 7bac7dc0d1..57fbd0bf75 100644 --- a/coregrind/m_initimg/initimg-darwin.c +++ b/coregrind/m_initimg/initimg-darwin.c @@ -61,7 +61,6 @@ static void load_client ( /*OUT*/ExeInfo* info, { const HChar* exe_name; Int ret; - SysRes res; vg_assert( VG_(args_the_exename) != NULL); exe_name = VG_(find_executable)( VG_(args_the_exename) ); @@ -76,12 +75,6 @@ static void load_client ( /*OUT*/ExeInfo* info, // The client was successfully loaded! Continue. - /* Get hold of a file descriptor which refers to the client - executable. This is needed for attaching to GDB. */ - res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); - if (!sr_isError(res)) - VG_(cl_exec_fd) = sr_Res(res); - /* Copy necessary bits of 'info' that were filled in */ *client_ip = info->init_ip; } diff --git a/coregrind/m_initimg/initimg-freebsd.c b/coregrind/m_initimg/initimg-freebsd.c index 6749e849fc..cb98eb9144 100644 --- a/coregrind/m_initimg/initimg-freebsd.c +++ b/coregrind/m_initimg/initimg-freebsd.c @@ -64,7 +64,6 @@ static void load_client ( /*OUT*/ExeInfo* info, { const HChar* exe_name; Int ret; - SysRes res; vg_assert( VG_(args_the_exename) != NULL); exe_name = VG_(find_executable)( VG_(args_the_exename) ); @@ -83,13 +82,6 @@ static void load_client ( /*OUT*/ExeInfo* info, // The client was successfully loaded! Continue. - /* Get hold of a file descriptor which refers to the client - executable. This is needed for attaching to GDB. */ - res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); - if (!sr_isError(res)) { - VG_(cl_exec_fd) = sr_Res(res); - } - /* Copy necessary bits of 'info' that were filled in */ *client_ip = info->init_ip; *client_toc = info->init_toc; @@ -342,6 +334,53 @@ static const struct auxv *find_auxv(const UWord* sp) return (const struct auxv *)sp; } +static Bool try_get_interp(const HChar* args_exe, HChar* interp_out) +{ + HChar hdr[4096]; + Int len = sizeof hdr; + SysRes res; + Int fd; + HChar* end; + HChar* cp; + HChar* interp; + + res = VG_(open)(args_exe, VKI_O_RDONLY, 0); + if (sr_isError(res)) { + return False; + } else { + fd = sr_Res(res); + } + + res = VG_(pread)(fd, hdr, len, 0); + + if (sr_isError(res)) { + VG_(close)(fd); + return False; + } else { + len = sr_Res(res); + } + + if (0 != VG_(memcmp)(hdr, "#!", 2)) { + VG_(close)(fd); + return False; + } + + end = hdr + len; + interp = hdr + 2; + while (interp < end && (*interp == ' ' || *interp == '\t')) + interp++; + + for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++) + ; + + *cp = '\0'; + + VG_(sprintf)(interp_out, "%s", interp); + + VG_(close)(fd); + return True; +} + /* ---------------------------------------------------------------- This sets up the client's initial stack, containing the args, @@ -425,6 +464,10 @@ static Addr setup_client_stack(const void* init_sp, vg_assert( VG_(args_for_client) ); const HChar *exe_name = VG_(find_executable)(VG_(args_the_exename)); + HChar interp_name[VKI_PATH_MAX]; + if (try_get_interp(exe_name, interp_name)) { + exe_name = interp_name; + } HChar resolved_name[VKI_PATH_MAX]; VG_(realpath)(exe_name, resolved_name); diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index 5359189bf6..feec1e5f11 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -70,7 +70,6 @@ static void load_client ( /*MOD*/ExeInfo* info, { const HChar* exe_name; Int ret; - SysRes res; vg_assert( VG_(args_the_exename) != NULL); exe_name = VG_(find_executable)( VG_(args_the_exename) ); @@ -88,12 +87,6 @@ static void load_client ( /*MOD*/ExeInfo* info, // The client was successfully loaded! Continue. - /* Get hold of a file descriptor which refers to the client - executable. This is needed for attaching to GDB. */ - res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); - if (!sr_isError(res)) - VG_(cl_exec_fd) = sr_Res(res); - /* Copy necessary bits of 'info' that were filled in */ *client_ip = info->init_ip; *client_toc = info->init_toc; diff --git a/coregrind/m_initimg/initimg-solaris.c b/coregrind/m_initimg/initimg-solaris.c index 1e9e3fd061..4fa94b8c4c 100644 --- a/coregrind/m_initimg/initimg-solaris.c +++ b/coregrind/m_initimg/initimg-solaris.c @@ -65,7 +65,6 @@ static void load_client(/*OUT*/ExeInfo *info, { const HChar *exe_name; Int ret; - SysRes res; vg_assert(VG_(args_the_exename)); exe_name = VG_(find_executable)(VG_(args_the_exename)); @@ -96,12 +95,6 @@ static void load_client(/*OUT*/ExeInfo *info, } VG_(strcpy)(out_exe_name, exe_name); - /* Get hold of a file descriptor which refers to the client executable. - This is needed for attaching to GDB. */ - res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR); - if (!sr_isError(res)) - VG_(cl_exec_fd) = sr_Res(res); - /* Set initial brk values. */ if (info->ldsoexec) { VG_(brk_base) = VG_(brk_limit) = -1; diff --git a/coregrind/m_ume/elf.c b/coregrind/m_ume/elf.c index a850a50cfa..bad7e5ee6b 100644 --- a/coregrind/m_ume/elf.c +++ b/coregrind/m_ume/elf.c @@ -41,6 +41,7 @@ #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free) #include "pub_core_vkiscnums.h" #include "pub_core_syscall.h" // VG_(strerror) +#include "pub_core_clientstate.h" #include "pub_core_ume.h" // self #include "priv_ume.h" @@ -876,6 +877,12 @@ Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info) VG_(free)(e->p); VG_(free)(e); + /* Get hold of a file descriptor which refers to the client + executable. This is needed for attaching to GDB. */ + SysRes res = VG_(dup)(fd); + if (!sr_isError(res)) + VG_(cl_exec_fd) = sr_Res(res); + return 0; } diff --git a/coregrind/m_ume/macho.c b/coregrind/m_ume/macho.c index 046d174933..6d65574e44 100644 --- a/coregrind/m_ume/macho.c +++ b/coregrind/m_ume/macho.c @@ -41,6 +41,7 @@ #include "pub_core_machine.h" // VG_ELF_CLASS (XXX: which should be moved) #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free) #include "pub_core_syscall.h" // VG_(strerror) +#include "pub_core_clientstate.h" #include "pub_core_ume.h" // self #include "priv_ume.h" @@ -857,6 +858,10 @@ Int VG_(load_macho)(Int fd, const HChar *name, ExeInfo *info) info->executable_path = VG_(strdup)("ume.macho.executable_path", name); + SysRes res = VG_(dup)(fd); + if (!sr_isError(res)) + VG_(cl_exec_fd) = sr_Res(res); + return 0; } diff --git a/none/tests/freebsd/Makefile.am b/none/tests/freebsd/Makefile.am index d1f7759ec9..667445aa15 100644 --- a/none/tests/freebsd/Makefile.am +++ b/none/tests/freebsd/Makefile.am @@ -11,6 +11,8 @@ EXTRA_DIST = \ auxv.stderr.exp-freebsd131 \ auxv.stderr.exp-freebsd14 \ auxv.stderr.exp-arm64 \ + auxv_script.vgtest \ + auxv_script.stderr.exp \ bug452274.vgtest \ bug452274.stderr.exp \ bug498317.vgtest bug498317.stderr.exp \ diff --git a/none/tests/freebsd/auxv_script b/none/tests/freebsd/auxv_script new file mode 100755 index 0000000000..7794012c1f --- /dev/null +++ b/none/tests/freebsd/auxv_script @@ -0,0 +1 @@ +#!./auxv diff --git a/none/tests/freebsd/auxv_script.stderr.exp b/none/tests/freebsd/auxv_script.stderr.exp new file mode 100644 index 0000000000..dcca09f63c --- /dev/null +++ b/none/tests/freebsd/auxv_script.stderr.exp @@ -0,0 +1,29 @@ +val: AT_PHDR int: 03 ptr: 0x........ +val: AT_PHENT int: 04 ptr: 0x........ +val: AT_PHNUM int: 05 ptr: 0x........ +val: AT_PAGESZ int: 06 ptr: 0x........ +val: AT_FLAGS int: 08 ptr: 0x........ +val: AT_ENTRY int: 09 ptr: 0x........ +val: AT_BASE int: 07 ptr: 0x........ +val: AT_EHDRFLAGS int: 24 ptr: 0x........ +val: AT_EXECPATH int: 15 ptr: 0x........ +EXECPATH: BASEDIR/valgrind/none/tests/freebsd/auxv +val: AT_OSRELDATE int: 18 ptr: 0x........ +val: AT_CANARY int: 16 ptr: 0x........ +val: AT_CANARYLEN int: 17 ptr: 0x........ +val: AT_NCPUS int: 19 ptr: 0x........ +val: AT_PAGESIZES int: 20 ptr: 0x........ +val: AT_PAGESIZESLEN int: 21 ptr: 0x........ +val: AT_IGNORE int: 01 ptr: 0x........ +val: AT_STACKPROT int: 23 ptr: 0x........ +val: AT_IGNORE int: 01 ptr: 0x........ +val: AT_ARGC int: 28 ptr: 0x........ +val: AT_ARGV int: 29 ptr: 0x........ +ARGV: ./auxv +val: AT_ENVC int: 30 ptr: 0x........ +val: AT_ENVV int: 31 ptr: 0x........ +val: AT_PS_STRINGS int: 32 ptr: 0x........ +PS_STRINGS ARGV: ./auxv +val: AT_IGNORE int: 01 ptr: 0x........ +val: AT_USRSTACKBASE int: 35 ptr: 0x........ +val: AT_USRSTACKLIM int: 36 ptr: 0x........ diff --git a/none/tests/freebsd/auxv_script.vgtest b/none/tests/freebsd/auxv_script.vgtest new file mode 100644 index 0000000000..ccd450a9a2 --- /dev/null +++ b/none/tests/freebsd/auxv_script.vgtest @@ -0,0 +1,4 @@ +prog: auxv_script +vgopts: -q +stderr_filter: filter_auxv +