]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
PR140178 Support opening /proc/self/exe
authorMark Wielaard <mark@klomp.org>
Sat, 6 Feb 2021 21:02:56 +0000 (22:02 +0100)
committerMark Wielaard <mark@klomp.org>
Sun, 7 Feb 2021 13:55:02 +0000 (14:55 +0100)
Some programs open /proc/self/exe to read some data. Currently valgrind
supports following the /proc/self/exe link (to the original binary, so you
could then open that), but directly opening /proc/self/exe will open the
valgrind tool, not the executable file itself.

Add ML_(handle_self_exe_open) which dups VG_(cl_exec_fd) if the file
to open is /proc/self/exe or /proc/<pid>/exe. And do the same for openat.

https://bugs.kde.org/show_bug.cgi?id=140178

NEWS
coregrind/m_syswrap/priv_syswrap-generic.h
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-linux.c

diff --git a/NEWS b/NEWS
index 57a3c27ec492557b03ad1d5cb453f5f867f96253..5342336eccd9c729fe0de90c1e61f50f931eedfa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,7 @@ To see details of a given bug, visit
   https://bugs.kde.org/show_bug.cgi?id=XXXXXX
 where XXXXXX is the bug number as listed below.
 
+140178  open("/proc/self/exe", ...); doesn't quite work
 345077  linux syscall execveat support (linux 3.19)
 369029  handle linux syscalls sched_getattr and sched_setattr
 n-i-bz  helgrind: If hg_cli__realloc fails, return NULL.
index 4717abac6536abb0b4af05f3caec5c45586c9aa3..c50b3139993925a72b92a773e141c35c93dd43d8 100644 (file)
@@ -106,6 +106,10 @@ extern Bool
 ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
                       int flags);
 
+extern Bool
+ML_(handle_self_exe_open)(SyscallStatus *status, const HChar *filename,
+                          int flags);
+
 /* Helper function for generic mprotect and linux pkey_mprotect. */
 extern void handle_sys_mprotect (ThreadId tid, SyscallStatus *status,
                                  Addr *addr, SizeT *len, Int *prot);
index 7d4b385a380befa59bf441c35ae91891cf3d58cf..3810f74744925e924c0df90308b03259f2d75c33 100644 (file)
@@ -4078,6 +4078,38 @@ Bool ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
 }
 #endif // defined(VGO_linux) || defined(VGO_solaris)
 
+#if defined(VGO_linux)
+Bool ML_(handle_self_exe_open)(SyscallStatus *status, const HChar *filename,
+                               int flags)
+{
+   HChar  name[30];   // large enough for /proc/<int>/exe
+
+   if (!ML_(safe_to_deref)((const void *) filename, 1))
+      return False;
+
+   /* Opening /proc/<pid>/exe or /proc/self/exe? */
+   VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+   if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/exe"))
+      return False;
+
+   /* Allow to open the file only for reading. */
+   if (flags & (VKI_O_WRONLY | VKI_O_RDWR)) {
+      SET_STATUS_Failure(VKI_EACCES);
+      return True;
+   }
+
+   SysRes sres = VG_(dup)(VG_(cl_exec_fd));
+   SET_STATUS_from_SysRes(sres);
+   if (!sr_isError(sres)) {
+      OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
+      if (off < 0)
+         SET_STATUS_Failure(VKI_EMFILE);
+   }
+
+   return True;
+}
+#endif // defined(VGO_linux)
+
 PRE(sys_open)
 {
    if (ARG2 & VKI_O_CREAT) {
@@ -4119,8 +4151,10 @@ PRE(sys_open)
       }
    }
 
-   /* Handle also the case of /proc/self/auxv or /proc/<pid>/auxv. */
-   if (ML_(handle_auxv_open)(status, (const HChar *)(Addr)ARG1, ARG2))
+   /* Handle also the case of /proc/self/auxv or /proc/<pid>/auxv
+      or /proc/self/exe or /proc/<pid>/exe. */
+   if (ML_(handle_auxv_open)(status, (const HChar *)(Addr)ARG1, ARG2)
+       || ML_(handle_self_exe_open)(status, (const HChar *)(Addr)ARG1, ARG2))
       return;
 #endif // defined(VGO_linux)
 
index 52074149d7a65baf763418d91a601a5a7d4121e2..fcc534454af2068c100f6392a175c08e0a5455f1 100644 (file)
@@ -5745,6 +5745,22 @@ PRE(sys_openat)
       return;
    }
 
+   /* And for /proc/self/exe or /proc/<pid>/exe case. */
+
+   VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
+   if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
+       && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0 
+           || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/exe") == 0)) {
+      sres = VG_(dup)( VG_(cl_exec_fd) );
+      SET_STATUS_from_SysRes( sres );
+      if (!sr_isError(sres)) {
+         OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
+         if (off < 0)
+            SET_STATUS_Failure( VKI_EMFILE );
+      }
+      return;
+   }
+
    /* Otherwise handle normally */
    *flags |= SfMayBlock;
 }