[1/1] rtld.c: prelink soname mismatch fix
Commit Message
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(-)
@@ -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;
}