Patchwork [1/1] rtld.c: prelink soname mismatch fix

login
register
mail settings
Submitter Maninder Singh
Date Oct. 5, 2015, 10:14 a.m.
Message ID <1444040051-3681-1-git-send-email-maninder1.s@samsung.com>
Download mbox | patch
Permalink /patch/8920/
State New
Headers show

Comments

Maninder Singh - Oct. 5, 2015, 10:14 a.m.
This patch fixes the issue wherein prelink verification by loader fails
when shared library soname is different from filename.

Method to verify the given issue:
1. Create shared library "libB.so" with same soname "libB.so"
2. Build a program that link to library "libB.so".
	#gcc test.c -o test -lB
3. Now replace the original "libB.so" with symlink, like below
	#ln -sf libA.so libB.so
	(libB.so -> libA.so)
4. When we prelink "test", library list section '.gnu.liblist' contains
   entries as below.
	0: libA.so        2014-12-02T04:28:40 0x95c929e5 0   0 //SONAME
5. A runtime, prelink verification faile due to mismatched dependency
   due to soname issue.
	expect libA.so, found /lib/libB.so in dependency order
	prelink checking: failed

The issue is prelink fills soname in gnu.liblist section but loader uses
filename for prelink verification during loading instead of soname.

So, now we are comparing soname of a library with .gnu.liblist section of
prelinked executable, after the original filename mismatch occurs.

Signed-off-by: Vaneet Narang <v.narang@samsung.com>
Signed-off-by: Maninder Singh <maninder1.s@samsung.com>
Reviewed-by: Ajeet Yadav <ajeet.y@samsung.com>
Reviewed-by: Doha Hwang <doha.hwang@samsung.com>
---
 elf/rtld.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

Patch

diff --git a/elf/rtld.c b/elf/rtld.c
index 1474c72..24dd07c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1927,6 +1927,7 @@  ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
     {
       ElfW(Lib) *liblist, *liblistend;
       struct link_map **r_list, **r_listend, *l;
+      const char *soname;
       const char *strtab = (const void *) D_PTR (main_map, l_info[DT_STRTAB]);
 
       assert (main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)] != NULL);
@@ -1961,7 +1962,14 @@  ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	    break;
 
 	  if (! _dl_name_match_p (strtab + liblist->l_name, l))
-	    break;
+	    {
+	      if (l->l_info[DT_SONAME] == NULL)
+	        break;
+	      soname = ((const char *) D_PTR (l, l_info[DT_STRTAB]) +
+	                  l->l_info[DT_SONAME]->d_un.d_val);
+	      if (strcmp(strtab + liblist->l_name, soname) != 0)
+	        break;
+	    }
 
 	  ++liblist;
 	}