Summary: | Failing dlopen can leave behind dangling GL (dl_initfirst) link map pointer | ||
---|---|---|---|
Product: | glibc | Reporter: | H.J. Lu <hjl.tools> |
Component: | dynamic-link | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | carlos, fweimer |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | 2.31 | ||
Target Milestone: | 2.31 | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
H.J. Lu
2020-01-15 23:58:12 UTC
Program received signal SIGSEGV, Segmentation fault. call_init (l=0x40e8f0, argc=argc@entry=2, argv=argv@entry=0x7ffeffffcdc8, env=env@entry=0x7ffeffffcde0) at dl-init.c:39 39 if (__builtin_expect (l->l_name[0], 'a') == '\0' (gdb) bt #0 call_init (l=0x40e8f0, argc=argc@entry=2, argv=argv@entry=0x7ffeffffcdc8, env=env@entry=0x7ffeffffcde0) at dl-init.c:39 #1 0x00007ffff7fe22c6 in call_init (env=0x7ffeffffcde0, argv=0x7ffeffffcdc8, argc=2, l=<optimized out>) at dl-init.c:86 #2 _dl_init (main_map=0x40fca0, argc=2, argv=0x7ffeffffcdc8, env=0x7ffeffffcde0) at dl-init.c:86 #3 0x00007ffff77419bd in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:182 #4 0x00007ffff7fe6198 in dl_open_worker (a=a@entry=0x7ffeffffc7e0) at dl-open.c:758 #5 0x00007ffff7741971 in __GI__dl_catch_exception (exception=<optimized out>, operate=<optimized out>, args=<optimized out>) at dl-error-skeleton.c:208 #6 0x00007ffff7fe5a1e in _dl_open (file=0x7ffeffffca50 "libnss_sss.so.2", mode=-2147483646, caller_dlopen=0x7ffff772a4a1 <nss_load_library+241>, nsid=-2, argc=2, argv=<optimized out>, env=0x7ffeffffcde0) at dl-open.c:837 #7 0x00007ffff7740ef1 in do_dlopen (ptr=ptr@entry=0x7ffeffffca20) at dl-libc.c:96 #8 0x00007ffff7741971 in __GI__dl_catch_exception ( exception=exception@entry=0x7ffeffffc9a0, operate=operate@entry=0x7ffff7740eb0 <do_dlopen>, args=args@entry=0x7ffeffffca20) at dl-error-skeleton.c:208 #9 0x00007ffff7741a23 in __GI__dl_catch_error ( objname=objname@entry=0x7ffeffffca00, errstring=errstring@entry=0x7ffeffffca08, mallocedp=mallocedp@entry=0x7ffeffffc9ff, operate=operate@entry=0x7ffff7740eb0 <do_dlopen>, args=args@entry=0x7ffeffffca20) at dl-error-skeleton.c:227 #10 0x00007ffff7740fe7 in dlerror_run ( operate=operate@entry=0x7ffff7740eb0 <do_dlopen>, args=args@entry=0x7ffeffffca20) at dl-libc.c:46 #11 0x00007ffff774105a in __GI___libc_dlopen_mode ( name=name@entry=0x7ffeffffca50 "libnss_sss.so.2", mode=mode@entry=-2147483646) at dl-libc.c:195 #12 0x00007ffff772a4a1 in nss_load_library (ni=ni@entry=0x409d90) at nsswitch.c:359 #13 0x00007ffff772acd9 in __GI___nss_lookup_function (ni=0x409d90, fct_name=<optimized out>, fct_name@entry=0x7ffff7795d0b "getservbyname_r") at nsswitch.c:456 --Type <RET> for more, q to quit, c to continue without paging--q Quit (gdb) f 1 #1 0x00007ffff7fe22c6 in call_init (env=0x7ffeffffcde0, argv=0x7ffeffffcdc8, argc=2, l=<optimized out>) at dl-init.c:86 86 call_init (GL(dl_initfirst), argc, argv, env); (gdb) Florian, Do you think this might have to do with the NODELETE reordering? There is /* Remember whether this object must be initialized first. */ if (l->l_flags_1 & DF_1_INITFIRST) GL(dl_initfirst) = l; libpthread.so.0 has 0x000000006ffffffb (FLAGS_1) Flags: NOW NODELETE INITFIRST _dl_close_worker unloaded libpthread.so.0 which left GL(dl_initfirst) unchanged. This patch: diff --git a/elf/dl-close.c b/elf/dl-close.c index 104c299209..2d426d8737 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -756,6 +756,9 @@ _dl_close_worker (struct link_map *map, bool force) if (imap->l_runpath_dirs.dirs != (void *) -1) free (imap->l_runpath_dirs.dirs); + if (imap == GL(dl_initfirst)) + GL(dl_initfirst) = NULL; + free (imap); } } seems to work. Thanks. Would you please post the patch to libc-alpha? I think it is correct. I will post my non-CET test case for this separately. (In reply to Florian Weimer from comment #4) > Thanks. Would you please post the patch to libc-alpha? I think it is > correct. > > I will post my non-CET test case for this separately. https://sourceware.org/ml/libc-alpha/2020-01/msg00333.html Fixed by commit 5177d85b0c050a2333a0c4165c938dd422013d05 Author: H.J. Lu <hjl.tools@gmail.com> Date: Thu Jan 16 06:45:36 2020 -0800 Clear GL(dl_initfirst) when freeing its link_map memory [BZ# 25396] We should clear GL(dl_initfirst) when freeing its link_map memory. Tested on Fedora 31/x86-64 with CET. Reviewed-by: Florian Weimer <fweimer@redhat.com> The master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a332bd1518af518c984fad73eba6f46dc5b2b2d4 commit a332bd1518af518c984fad73eba6f46dc5b2b2d4 Author: Florian Weimer <fweimer@redhat.com> Date: Thu Jan 16 16:53:58 2020 +0100 elf: Add elf/tst-dlopenfail-2 [BZ #25396] Without CET, a jump into a newly loaded object through an overwritten link map often does not crash, it just executes some random code. CET detects this in some cases because the function pointer does not point to the start of a function in the replacement shared object, so there is no ENDBR instruction. The new test uses a small shared object and the existing dangling link map to trigger the bug. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |