This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RTLD DT_RUNPATH/DT_RPATH processing difference


Hello,

Recently I started the migration from DT_RPATH to DT_RUNPATH in our distro in
order to make the LD_LIBRARY_PATH work the right way, and detected that these
two tags are processed differently in RTLD.

We have a loader which opens executables (pie ones) with dlopen() and then
calls main(). This approach allows to speedup running application with large
number library dependencies.

Usual application has the following structure:

app/
    bin/app
    lib/library.so

During the launch procedure 'bin/app' is opened by loader and executed through
the dlopen().

In order to load the application-specific library.so the directory is changed
to app/lib and 'loader' has DT_RPATH set to ":" to allow loading from current
working directory.

After changing DT_RPATH to DT_RUNPATH the mechanism stopped working. I
investigated the elf/dl-load.c and found that 'main_map' and dependent objects
rpaths are only checked in case of DT_RPATH tag.

Can someone tell if this behavior is intended or not?

I've prepared a patch to process these places for DT_RUNPATH and resolved the
launcher issue. The patch and reprocase are attached.

Best Regards,
Vyacheslav Barinov
>From e3579769f447e7222a08e031b2f678d25bb3ff52 Mon Sep 17 00:00:00 2001
From: Slava Barinov <v.barinov@samsung.com>
Date: Wed, 28 Jun 2017 11:49:56 +0300
Subject: [PATCH] elf: Treat DT_RUNPATH exactly like DT_RPATH in rtld

        * elf/dl-load.c: Add handling of DT_RUNPATH for dependent objects and
        executable itself.

Now situations
loader.elf[RPATH=:]   -> app.elf -> library.so
loader.elf[RUNPATH=:] -> app.elf -> library.so
are processed equally.

Signed-off-by: Slava Barinov <v.barinov@samsung.com>
---
 elf/dl-load.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index c0d6249373..bd33b5f587 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -2072,6 +2072,40 @@ _dl_map_object (struct link_map *loader, const char *name,
 			loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
 			LA_SER_LIBPATH, &found_other_class);

+      if (loader != NULL && loader->l_info[DT_RUNPATH] != NULL)
+	{
+	  /* This is the executable's map (if there is one).  Make sure that
+	     we do not look at it twice.  */
+	  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+	  bool did_main_map = false;
+
+	  /* First try the DT_RUNPATH of the dependent object that caused NAME
+	     to be loaded.  Then that object's dependent, and on up.  */
+	  for (l = loader; l; l = l->l_loader)
+	    if (cache_rpath (l, &l->l_runpath_dirs, DT_RUNPATH, "RUNPATH"))
+	      {
+		fd = open_path (name, namelen, mode,
+				&l->l_runpath_dirs,
+				&realname, &fb, loader, LA_SER_RUNPATH,
+				&found_other_class);
+		if (fd != -1)
+		  break;
+
+		did_main_map |= l == main_map;
+	      }
+
+	  /* If dynamically linked, try the DT_RUNPATH of the executable
+	     itself.  NB: we do this for lookups in any namespace.  */
+	  if (fd == -1 && !did_main_map
+	      && main_map != NULL && main_map->l_type != lt_loaded
+	      && 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, loader ?: main_map, LA_SER_RUNPATH,
+			    &found_other_class);
+	}
+
       /* Look at the RUNPATH information for this binary.  */
       if (fd == -1 && loader != NULL
 	  && cache_rpath (loader, &loader->l_runpath_dirs,
--
2.13.1

Attachment: dlopen-test.tar.xz
Description: application/xz


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]