Bug 1449604 - CC 6.3 libasan.so intercepts dlopen but does not taken the search path from the original module into account
Summary: CC 6.3 libasan.so intercepts dlopen but does not taken the search path from t...
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Red Hat Developer Toolset
Classification: Red Hat
Component: gcc
Version: DTS 6.0 RHEL 7
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: alpha
: 6.1
Assignee: Marek Polacek
QA Contact: Martin Cermak
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2017-05-10 10:58 UTC by Piyush Bhoot
Modified: 2023-09-07 18:54 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-06-24 15:09:23 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker DTS-698 0 None None None 2023-09-07 18:54:08 UTC
Sourceware 25114 0 P2 NEW RFE: Provide dlopen API(s) that allows caller to identify resolution scope (required by ASAN). 2020-06-24 15:08:41 UTC

Description Piyush Bhoot 2017-05-10 10:58:50 UTC
Description of problem:

Using gcc6.3 libasan may - under certain circumstances - cause dlopen fail to find the .so library when only the name of the library is used in the call to dlopen (not the relative path).

Version-Release number of selected component (if applicable):
devtoolset-6-gcc-6.3.1-3.1.el7.x86_64
devtoolset-6-libasan-devel-6.3.1-3.1.el7.x86_64


How reproducible:
Alaways

Steps to Reproduce:
1.
#include <dlfcn.h>
#include <iostream>
int main()
{
    void *handle = dlopen("libb.so", RTLD_NOW);
    if (handle == NULL) {
        std::cout << "Failed to load libb.so" << std::endl;
    }
}

#mkdir lib
#g++ --sanitize=address -Wl,-rpath='$ORIGIN/lib' -Wl,--enable-new-dtags -ldl -o main main.cpp
#cd lib; 

Create libb.so: 
int foo()
{
  return 1;
}

g++ -fPIC -shared b.C -o libb.so

Actual results:

strace ./main 2>&1 | grep libb.so
open("/opt/rh/devtoolset-6/root/usr/lib/../lib64/tls/libb.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
:
<snipped>
:
open("/usr/lib64/libb.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(1, "Failed to load libb.so\n", 23Failed to load libb.so

Expected results:

strace ./main 2>&1 | grep libb.so

open("/opt/rh/devtoolset-6/root/usr/lib64/tls/libb.so", O_RDONLY) = -1 ENOENT (No such file or directory)

open("/root/cc/lib/libb.so", O_RDONLY)  = 3


Additional info:
Libasan intercepts dlopen call and the libasan's RUNPATH is taken into account, not the binary one. Running it through strace, it failed to load libb.so

Comment 4 Florian Weimer 2017-05-10 11:39:04 UTC
I think the libasan dlopen interceptor could be turned into a tail call, which would address the issue.

#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                           \
  if (flags()->strict_init_order) {                                            \
    StopInitOrderChecking();                                                   \
  }

The above probably could just as well happen before the dlopen call.

Comment 6 Jakub Jelinek 2019-01-08 13:16:17 UTC
(In reply to Florian Weimer from comment #4)
> I think the libasan dlopen interceptor could be turned into a tail call,
> which would address the issue.
> 
> #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag)                        
> \
>   if (flags()->strict_init_order) {                                         
> \
>     StopInitOrderChecking();                                                
> \
>   }
> 
> The above probably could just as well happen before the dlopen call.

I don't see how.  The interceptor does some work before the dlopen call and other work after it:
INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
  void *ctx;
  COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
  if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
  COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
  void *res = REAL(dlopen)(filename, flag);
  Symbolizer::GetOrInit()->InvalidateModuleList();
  COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
  return res;
}


Note You need to log in before you can comment on or make changes to this bug.