Bug 86921

Summary: /proc/self/exe is not set properly when valgrind is involved
Product: [Developer tools] valgrind Reporter: smile <smilenglitter>
Component: generalAssignee: Julian Seward <jseward>
Status: RESOLVED FIXED    
Severity: normal CC: frank.wallingford, rjwalsh
Priority: NOR    
Version: 2.1.2   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: Patch to make readlink on /proc/self/exe work

Description smile 2004-08-10 16:20:48 UTC
Version:           2.1.2 (using KDE KDE 3.2.3)
Installed from:    Unspecified
Compiler:          gcc (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-34) 
OS:                Linux

The link /proc/self/exe has no target when a program is run under valgrind.

A simple testcase:

$ ls -l /proc/self/exe              lrwxrwxrwx    1 msadasiv g900            0 Aug 10 07:09 /proc/self/exe -> /bin/ls
$ valgrind --tool=addrcheck ls -l /proc/self/exe
==12470== Warning: ignored attempt to set SIGKILL handler in sigaction();
==12470==          the SIGKILL signal is uncatchable
==12470== Warning: ignored attempt to set SIGSTOP handler in sigaction();
==12470==          the SIGSTOP signal is uncatchable
ls: cannot read symbolic link /proc/self/exe: No such file or directory
lrwxrwxrwx    1 msadasiv g900            0 Aug 10 07:08 /proc/self/exe


Another testcase:

Following is a simple C code just printing the content of the link

$ cat proc_self.c 
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

/*Finds the path containing the currently running program executable.
The path is placed into BUFFER,which is of length LEN.Returns
the number of characters in the path,or -1 on error.*/

int main () { 
        char path [PATH_MAX ]; 

        /*Read the target of /proc/self/exe.*/ 
        if (readlink ("/proc/self/exe", path, PATH_MAX) <= 0){
                printf("%s\n","readline error");
                return -1; 
        } else {
                printf("%s\n", path);
        }

        return 0; 
}

$ gcc -g -o proc_self proc_self.c
$ valgrind --tool=addrcheck -q proc_self
readline error
$ proc_self
/home/msadasiv/prgs/exe/proc_self
$ 


/proc/self though points to the right pid.
/proc/self/exe has no target
Comment 1 Tom Hughes 2004-08-10 17:01:23 UTC
I suspect this will be very hard to fix. The problem is that as far as the kernel is concerned, the executable is /usr/bin/valgrind, but that has actually been unmapped once stage2 is loaded.

What proc_exe_link() in fs/proc/base.c in the kernel does is look through the target process's memory mappings for one with the VM_EXECUTABLE flag set and then return the file from which that memory is mapped as the target of the link. Because /usr/bin/valgrind has been unmapped it doesn't find such a mapping so returns ENOENT instead.

It's possible that making valgrind's ELF loader set MAP_EXECUTABLE when it maps the target program will fix this...

Otherwise what we would probably have to do to fix this is to special case the readlink system call to spot these attempts and return a suitable value.
Comment 2 Tom Hughes 2004-08-10 17:14:33 UTC
It seems that mmap deliberately clears MAP_EXECUTABLE from the passed flags so it is impossible for a user program to cause VM_EXECUTABLE to be set on a mapping.

Hence the only solution would be a hack in the readlink system call.
Comment 3 Nicholas Nethercote 2004-08-10 21:31:01 UTC
Would read() have to be wrapped as well?  And readv(), and any similar syscalls?

Smile/Madhan, did you cause a problem for you in a real program?  (I'm trying to gauge how important it is.)
Comment 4 Tom Hughes 2004-08-11 13:30:07 UTC
We wouldn't need to wrap read because if you open a symbol link and read from it you are actually reading from the file that is the target of the link. It's only readlink that allows you to see where there link is pointing.
Comment 5 smile 2004-08-12 11:02:03 UTC
This is part of Oracle's routines to get the executable path/name. Later ELF parsing is done to get routine names from PC address for getting stack trace and other routines.

Alternative ofcourse is to resort back to the usual way of looking at CWD and PATH and finding the executable.

I have used readlink() in the sample program, in the real scenario a direct open() is used.
Comment 6 Tom Hughes 2004-09-25 12:18:36 UTC
*** Bug 89637 has been marked as a duplicate of this bug. ***
Comment 7 Tom Hughes 2004-09-25 12:48:46 UTC
Created attachment 7671 [details]
Patch to make readlink on /proc/self/exe work

This (fairly horrible) patch makes readlink on /proc/self/exe (and
/proc/<client-pid>/exe) work by special casing it in the readlink system call
wrapper.
Comment 8 smile 2004-09-28 13:34:14 UTC
The patch fixes the problem with readlink. Can you also extend this to a direct fopen.
Comment 9 Tom Hughes 2004-09-28 13:57:39 UTC
Arrgh. I was wrong of course in my previous comment about open because although open does open the target of the link it can only do that if the kernel can manage to resolve the link.

Unfortunately I'm not sure that it's going to be sensible to perform the file name mapping done here for all the system calls that work with filenames as it would just get silly. We may just have to leave this as something that can't be simulated fully.
Comment 10 smile 2004-09-29 07:37:48 UTC
I agree with you. The readlink is a usable workaround. Thanks. If it makes sense can we move this to the wishlist.
Comment 11 Jeremy Fitzhardinge 2004-11-24 01:34:59 UTC
I think Robert fixed this one.
Comment 12 Jeremy Fitzhardinge 2005-01-20 20:24:39 UTC
readlink returns useful info for /proc/self/exe.  I also made open on /proc/self/exe work.  Both are hacks, not general solutions, but they'll do for now...