Bug 140178 - open("/proc/self/exe, ...); doesn't quite work
Summary: open("/proc/self/exe, ...); doesn't quite work
Status: RESOLVED FIXED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: 3.2.1
Platform: Ubuntu Linux
: NOR normal
Target Milestone: ---
Assignee: Julian Seward
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-17 02:32 UTC by Maxime Austruy
Modified: 2021-02-07 13:57 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Handle open /proc/self/exe (2.53 KB, text/plain)
2021-02-06 20:54 UTC, Mark Wielaard
Details
Updated patch that also handle openat (3.86 KB, text/plain)
2021-02-07 01:42 UTC, Mark Wielaard
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Maxime Austruy 2007-01-17 02:32:05 UTC
Sorry in advance if this is a dupe.

I encountered this bug at work on a 64bit ubuntu dapper box. It has version
3.2.0 installed, but my debian unstable box (running 3.2.1) at home also shows
the same problem.

See the code snippet below. readlink("/proc/self/exe", ...) is properly handled
but open("/proc/self/exe", ...) is not. 

According to this page:
  http://valgrind.org/docs/manual/dist.news.html
this bug got filed & fixed between 2.2.0 and 2.4.0, but a regression seems to
have crept in.

The native output of the program attached below is:

[maustruy@cahors ~/test_code/valgrind-proc-self-bug]$ ./test
/proc/12474/fd/3 -> /exit14/home/maustruy/test_code/valgrind-proc-self-bug/test

but:

[maustruy@cahors ~/test_code/valgrind-proc-self-bug]$ valgrind -q ./test
/proc/12490/fd/3 -> /usr/lib/valgrind/amd64-linux/memcheck

--
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(void)
{
   char str[1024];
   char buf[1024];
   int fd;
   int s;

   fd = open("/proc/self/exe", O_RDONLY);
   if (fd == -1) {
      return 1;
   }

   sprintf(str, "/proc/%d/fd/%d", getpid(), fd);
   s = readlink(str, buf, sizeof buf);
   if (s != -1) {
      buf[s] = '\0';
      printf("%s -> %s\n", str, buf);
   }

   close(fd);
   return 0;
}
Comment 1 Jeremy Fitzhardinge 2007-01-17 05:45:16 UTC
Yes.  Dealing with /proc/self/exe is a very special-case hack, originated by strange things done by the OpenOffice startup wrapper.  If you need /proc/<pid>/exe to work then that would need to be added as another special case.  This is basically a tricky area because of how Valgrind works.
Comment 2 Maxime Austruy 2007-01-17 22:41:48 UTC
Jeremy, are you saying that the code in valgrind that handles /proc/self/exe is known to work well and that only /proc/<pid>/exe  is not currently handled? I'm not sure I understand your comment.

Unless I'm missing something, it seems that /proc/self/exe doesn't work as it should. To not expose any more valgrind incompleteness problem, I've modified the code snipped above to do:

  printf("fd=%d\n", fd);
  while (1) { sleep(1); }

after the call to open("/proc/self/exe", ...);

then:

[maustruy@cahors ~/test_code/valgrind-proc-self-bug]$ valgrind -q ./test
fd=3

and by "manually" browsing /proc/<pid>/fd, I see:

[maustruy@cahors ~]$ ps ax|grep valgrind
 7620 pts/30   S+     0:00 /usr/bin/valgrind.bin -q ./test
 7622 pts/31   S+     0:00 grep valgrind
[maustruy@cahors ~]$ cd /proc/7620/fd/
[maustruy@cahors /proc/7620/fd]$ dir
total 0
dr-x------ 2 maustruy mts  0 2007-01-17 13:30 .
dr-xr-xr-x 4 maustruy mts  0 2007-01-17 13:30 ..
lrwx------ 1 maustruy mts 64 2007-01-17 13:30 0 -> /dev/pts/30
lrwx------ 1 maustruy mts 64 2007-01-17 13:30 1 -> /dev/pts/30
lr-x------ 1 maustruy mts 64 2007-01-17 13:30 1014 -> /exit14/home/maustruy/test_code/valgrind-proc-self-bug/test
lrwx------ 1 maustruy mts 64 2007-01-17 13:30 1015 -> /tmp/valgrind_proc_7620_cmdline_6AE85886 (deleted)
lrwx------ 1 maustruy mts 64 2007-01-17 13:30 1016 -> /dev/pts/30
lr-x------ 1 maustruy mts 64 2007-01-17 13:30 1017 -> pipe:[4114564]
l-wx------ 1 maustruy mts 64 2007-01-17 13:30 1018 -> pipe:[4114564]
lrwx------ 1 maustruy mts 64 2007-01-17 13:30 2 -> /dev/pts/30
lr-x------ 1 maustruy mts 64 2007-01-17 13:30 3 -> /usr/lib/valgrind/amd64-linux/memcheck      <---- XXX
Comment 3 Robert Walsh 2007-01-17 23:52:08 UTC
Yeah - this is only intercepted for readlink/readlinkat right now.  Look in m_syswrap/syswrap-generic.c and m_syswrap/syswrap-linux.c.  Open is not handled because we weren't aware that anyone actually opened /proc/self/exe.  This should probably be expanded to deal with all syscalls that might be effected by this, not just readlink and readlinkat.

BTW: /proc/<fd>/fd/<x> should be OK without needing any special handling when this is fixed up.
Comment 4 Mark Wielaard 2021-02-06 20:54:56 UTC
Created attachment 135468 [details]
Handle open /proc/self/exe

Also reported at https://bugzilla.redhat.com/show_bug.cgi?id=1925786
Comment 5 Mark Wielaard 2021-02-07 01:42:47 UTC
Created attachment 135476 [details]
Updated patch that also handle openat

The fix needs to handle both the open and openat syscalls.
Comment 6 Mark Wielaard 2021-02-07 13:57:27 UTC
Tested as part of https://bugzilla.redhat.com/show_bug.cgi?id=1925786

commit 57c823aefea32e1fba3af47d29e66313d0bc13cd
Author: Mark Wielaard <mark@klomp.org>
Date:   Sat Feb 6 22:02:56 2021 +0100

    PR140178 Support opening /proc/self/exe
    
    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