public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* DT_RUNPATH of executable not found when loader and dl_caller is libasan.so
       [not found] <CALO2TqLALAdwci2eFvYb3QZ6K_-2Eg8nu339VQ=23Mmq20jY+g@mail.gmail.com>
@ 2021-02-26 17:29 ` Navin P
  2021-03-03 17:51   ` Florian Weimer
  0 siblings, 1 reply; 2+ messages in thread
From: Navin P @ 2021-02-26 17:29 UTC (permalink / raw)
  To: libc-alpha

Hi,
    I sent this to libc-help which seems to
the wrong group.

 My scenario is    $HOME/package/ contains ./a.out and dso libplugin.so.
  Without address sanitizer(asan) libasan.so mode using gcc , if i run
./a.out from $HOME/package i'm able to find libplugin.so and it prints
dlopen succeeded.
Now if i go to the parent directy and cd ..  . If i run
./package/a.out , it is able to find and prints dlopen succeeded .
Everything is good until here.
libplugin.so is an empty shared object without asan..

#include<dlfcn.h>
#include<cstdio>

int main(){
        void *handle=dlopen("libplugin.so",RTLD_NOW);
        if(handle!=NULL){
                printf("dlopen succeeded\n");
        } else {
                printf("dlopen failed\n");
        }
        return 0;
}


Now i compile the example and .so with -fsanitize=address. Now in the
case of running a.out from  $HOME/package , it prints dlopen
succeeded.
Now if i do cd.. and run ./package/a.out from $HOME it fails and
prints dlopen failed. This is because the loader is changed to
libasan.so and this
time the DT_RUNPATH is checked for RUNPATH of libasan. This works for
RPATH because we check for all the list of loaders and we find the
base loader whose rpath is $HOME/package. But in case of DT_RUNPATH we
don't .
I think an additional lookup needs to be performed after the old
RUNPATH code in dl-load.c which looks up for
GL(dl_ns)[LM_ID_BASE]._ns_loaded when fd==-1.

I've tested this patch and it works fine for me.

From d2cb9bba3de58af3516eb7099d0452e2ee6365d2 Mon Sep 17 00:00:00 2001
From: Navin P <navinp0304@gmail.com>
Date: Mon, 22 Feb 2021 15:02:00 +0530
Subject: [PATCH] If executables are compiled with asan, it should perform
 additional LM_ID_BASE D_RUNPATH also.

---
 elf/dl-load.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 9e2089cfaa..fe88c8c9ea 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -2161,6 +2161,34 @@ _dl_map_object (struct link_map *loader, const
char *name,
  &loader->l_runpath_dirs, &realname, &fb, loader,
  LA_SER_RUNPATH, &found_other_class);

+      /*
+       * This is not transitive dependency.It it just an additional
+       * lookup into executable/dso runpath when loader is different
+       * from LM_ID_BASE loader.
+       * In usual cases like direct call to executable, then main_map
+       * is same as loader and no lookup is performed.
+       * In cases like libasan.so being the parent caller with dl_caller
+       * set to libasan.so which is called by GL(dls_ns)[LIM_ID_BASE],
+       * we need to additionally search the executable/dso link_map
+       * other than loader link_map which is performed above.
+       */
+      struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
+      /* Look at the RUNPATH information for this binary using main_map.
+       * This lookup is only done when the binary is in namespace 0.
+       * For nested namespaces from dlmopen LM_ID_NEWLM, we don't search
+       * in namespace 0 because it is detached from LM_ID_BASE.
+       * In that case lookup is done in the callers RUNPATH above.
+       */
+
+      if (fd == -1 && (nsid == LM_ID_BASE ) && main_map != NULL
+          && main_map != loader
+   && cache_rpath (main_map, &main_map->l_runpath_dirs,
+   DT_RUNPATH, "RUNPATH"))
+ fd = open_path (name, namelen, mode,
+ &main_map->l_runpath_dirs, &realname, &fb, main_map,
+ LA_SER_RUNPATH, &found_other_class);
+
       if (fd == -1)
         {
           realname = _dl_sysdep_open_object (name, namelen, &fd);
-- 
2.25.1

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: DT_RUNPATH of executable not found when loader and dl_caller is libasan.so
  2021-02-26 17:29 ` DT_RUNPATH of executable not found when loader and dl_caller is libasan.so Navin P
@ 2021-03-03 17:51   ` Florian Weimer
  0 siblings, 0 replies; 2+ messages in thread
From: Florian Weimer @ 2021-03-03 17:51 UTC (permalink / raw)
  To: Navin P via Libc-alpha

* Navin P. via Libc-alpha:

> Hi,
>     I sent this to libc-help which seems to
> the wrong group.
>
>  My scenario is    $HOME/package/ contains ./a.out and dso libplugin.so.
>   Without address sanitizer(asan) libasan.so mode using gcc , if i run
> ./a.out from $HOME/package i'm able to find libplugin.so and it prints
> dlopen succeeded.
> Now if i go to the parent directy and cd ..  . If i run
> ./package/a.out , it is able to find and prints dlopen succeeded .
> Everything is good until here.
> libplugin.so is an empty shared object without asan..
>
> #include<dlfcn.h>
> #include<cstdio>
>
> int main(){
>         void *handle=dlopen("libplugin.so",RTLD_NOW);
>         if(handle!=NULL){
>                 printf("dlopen succeeded\n");
>         } else {
>                 printf("dlopen failed\n");
>         }
>         return 0;
> }
>
>
> Now i compile the example and .so with -fsanitize=address. Now in the
> case of running a.out from  $HOME/package , it prints dlopen
> succeeded.
> Now if i do cd.. and run ./package/a.out from $HOME it fails and
> prints dlopen failed. This is because the loader is changed to
> libasan.so and this
> time the DT_RUNPATH is checked for RUNPATH of libasan. This works for
> RPATH because we check for all the list of loaders and we find the
> base loader whose rpath is $HOME/package. But in case of DT_RUNPATH we
> don't .
> I think an additional lookup needs to be performed after the old
> RUNPATH code in dl-load.c which looks up for
> GL(dl_ns)[LM_ID_BASE]._ns_loaded when fd==-1.

I think the current glibc behavior is correct because libasan calls
dlopen in your example.  So the RUNPATH on libasan has to be used, and
not the RUNPATH on the main executable.

Or put differently, this is a known limitation of libasan's
interposed-based approach.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-03-03 17:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CALO2TqLALAdwci2eFvYb3QZ6K_-2Eg8nu339VQ=23Mmq20jY+g@mail.gmail.com>
2021-02-26 17:29 ` DT_RUNPATH of executable not found when loader and dl_caller is libasan.so Navin P
2021-03-03 17:51   ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).