Bug 396415 - Valgrind is not looking up $ORIGIN rpath of shebang programs
Summary: Valgrind is not looking up $ORIGIN rpath of shebang programs
Status: REPORTED
Alias: None
Product: valgrind
Classification: Developer tools
Component: general (show other bugs)
Version: 3.10.0
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Julian Seward
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-07-11 17:53 UTC by Jack Zhao
Modified: 2018-07-13 00:33 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
repro case (993 bytes, application/gzip)
2018-07-13 00:33 UTC, Jack Zhao
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jack Zhao 2018-07-11 17:53:02 UTC
> uname -a
Linux zanarkand 3.10.0-693.2.2.el7.x86_64 #1 SMP Sat Sep 9 03:55:24 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

> valgrind --version
valgrind-3.10.0

-----

Steps to reproduce:


1. Write a bare-minimum library with something that can be included. Mine looked like this:

> cat foo.h
extern void doSomething(void);

> cat foo.cpp 
#include <iostream>

void doSomething(void) {
    std::cout << "did something" << std::endl;
}


2. Write a bare-minimum program that accepts a file as an argument and does something to the file. Make sure to include the library we just made and invoke its function. In my case I made it just print the file contents to stdout after invoking the doSomething function. See:

> cat main.cpp 
#include <iostream>
#include <fstream>
#include <string>
#include "foo.h"

int main(int argc, char* argv[]) {
    doSomething();
    if (argc != 2) {
        std::cerr << "one parameter, should be file path" << std::endl;
    }
    std::string line;
    std::ifstream myfile(argv[1]);
    if (myfile.is_open()) {
        while(getline(myfile, line)) {
            std::cout << line << std::endl;
        }
        myfile.close();
    }
}


3. Build the library as a shared object (i.e. libfoo.so)

4. Build the main program with the following rpath: $ORIGIN/../lib, see:

> readelf -d main

Dynamic section at offset 0x1de8 contains 28 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libfoo.so]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [$ORIGIN/../lib]
 0x000000000000000c (INIT)               0x400c90
 0x000000000000000d (FINI)               0x401104
 0x0000000000000019 (INIT_ARRAY)         0x601dc8
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x601dd8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x4005e8
 0x0000000000000006 (SYMTAB)             0x4002e8
 0x000000000000000a (STRSZ)              976 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x602000
 0x0000000000000002 (PLTRELSZ)           480 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400ab0
 0x0000000000000007 (RELA)               0x400a68
 0x0000000000000008 (RELASZ)             72 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x4009f8
 0x000000006fffffff (VERNEEDNUM)         3
 0x000000006ffffff0 (VERSYM)             0x4009b8
 0x0000000000000000 (NULL)               0x0

5. Put the library and main program in the following directories:

test_repro/lib/libfoo.so
test_repro/bin/main

6. Create the following file at the following location with a shebang line that points to main:

test_repro/script/subdir/myscript (the `subdir` is important here)

> cat myscript
#!/path/to/my/test_repro/bin/main
lorem ipsum

7. Make the 'myscript' file executable, and run it. It should work - main gets invoked as the program to feed the file into, and main is able to load in libfoo.so.

8. Run myscript through valgrind (i.e. `valgrind ./myscript`) and observe that it fails to load libfoo.so

-----

Note that:

 - issue does not happen when running `valgrind /path/to/my/test_repro/bin/main myscript` (i.e. when execution does not depend on shebang)

 - issue does not happen when rpath contains an absolute path to /path/to/my/test_repro/lib, only when rpath relies on $ORIGIN

 - issue does not happen if I put `myscript` into `test_repro/script` instead of `test_repro/script/subdir`. This suggests that $ORIGIN path is processed but treated as path relative to `myscript` instead of path relative to the shebang program `main`.


Anyway, thanks!
Comment 1 Tom Hughes 2018-07-11 18:05:38 UTC
I don't think we have any code which does searching for dynamic libraries - we just load the interpreter (ie ld.so) and then let that do the actual dynamic linking.

So this must be some environmental difference - either literally in the environment variables, or in the auxilliary vector or something.
Comment 2 Jack Zhao 2018-07-13 00:33:12 UTC
Hi, thanks for the response. For what it's worth, I was able to reproduce this with a barebones centos7 container. Please see log here: https://pastebin.com/raw/VbvL0khy

Steps I took:

1. run a container of the centos:7 official image available from docker.io

    sudo docker run -i -t centos:7 /bin/bash

2. once in container, install gcc, gcc-c++, and valgrind

    yum install -y gcc gcc-c++ valgrind

3. download the attached repro case from some available server (or use any method to get the repro case into the container)

    curl http://<some_server>/test_repro.tar.gz

4. unpack the repro case

    tar xvzf test_repro.tar.gz

5. cd into the test_repro folder

    cd test_repro

6. run repro.sh

    ./repro.sh

The test_repro.tar.gz will be attached right after.

So if it's an environment-induced problem, it seems to happen in default/typical environments. Any guidance on what kind of environment settings might be causing it? Thanks!
Comment 3 Jack Zhao 2018-07-13 00:33:40 UTC
Created attachment 113911 [details]
repro case