From c5bfe03733aa9920825f34a62573d5912b7eb1ce Mon Sep 17 00:00:00 2001 From: Snaipe Date: Tue, 6 Sep 2016 20:03:36 +0200 Subject: [PATCH] section: Resolve /proc/self/exe for compatibility with introspection tools like valgrind --- src/compat/section-elf.c | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/compat/section-elf.c b/src/compat/section-elf.c index 6b7760c..516be36 100644 --- a/src/compat/section-elf.c +++ b/src/compat/section-elf.c @@ -23,33 +23,52 @@ */ #include "section.h" +#include +#include +#include #include #include -#include #include static int open_self(void) { -#if defined __linux__ - return open("/proc/self/exe", O_RDONLY); +#if defined (__linux__) + const char *self = "/proc/self/exe"; #elif defined __NetBSD__ - return open("/proc/curproc/exe", O_RDONLY) + const char *self = "/proc/curproc/exe"; #elif defined __FreeBSD__ - int fd = open("/proc/curproc/file", O_RDONLY); - /* Fallback */ - if (fd == -1 && errno == ENOENT) { - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - char path[PATH_MAX]; - size_t cb = sizeof (path); - sysctl(mib, sizeof (mib) / sizeof (int), path, &cb, NULL, 0); - fd = open(path, O_RDONLY); - } - return fd; + char self[PATH_MAX]; + + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t cb = sizeof (self); + sysctl(mib, sizeof (mib) / sizeof (int), self, &cb, NULL, 0); #elif defined __OpenBSD__ || defined __DragonFly__ - return open("/proc/curproc/file", O_RDONLY) + const char *self = "/proc/curproc/file"; #else + errno = ENOTSUP; return -1; #endif + + /* We can't just use /proc/self/exe or equivalent to re-exec the + executable, because tools like valgrind use this path to open + and map the ELF file -- which would point to the valgrind binary. */ + char fullpath[PATH_MAX]; + ssize_t rc = readlink(self, fullpath, PATH_MAX); + if (rc == -1) { + if (errno == EINVAL) { + strncpy(fullpath, self, PATH_MAX); + goto do_open; + } + return -1; + } + if ((size_t) rc == PATH_MAX) { + errno = ENAMETOOLONG; + return -1; + } + memset(fullpath + rc, 0, PATH_MAX - rc); + +do_open: + return open(fullpath, O_RDONLY); } static int open_module_map(mod_handle *mod)