This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Detecting multiple libcs
- From: Carlos O'Donell <carlos at redhat dot com>
- To: Florian Weimer <fweimer at redhat dot com>, GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 3 Jun 2016 15:22:39 -0400
- Subject: Re: Detecting multiple libcs
- Authentication-results: sourceware.org; auth=none
- References: <70540d36-1515-629d-3133-494ad8061f2d at redhat dot com> <5751B553 dot 6050207 at redhat dot com> <6bd59def-ba74-d248-c894-f12d67c51c4b at redhat dot com>
On 06/03/2016 02:10 PM, Florian Weimer wrote:
> On 06/03/2016 06:50 PM, Carlos O'Donell wrote:
>> On 06/03/2016 10:50 AM, Florian Weimer wrote:
>>> ptmalloc_init has this code:
>>>
>>> #ifdef SHARED
>>> /* In case this libc copy is in a non-default namespace, never use brk.
>>> Likewise if dlopened from statically linked program. */
>>> Dl_info di;
>>> struct link_map *l;
>>>
>>> if (_dl_open_hook != NULL
>>> || (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0
>>> && l->l_ns != LM_ID_BASE))
>>> __morecore = __failing_morecore;
>>> #endif
>>>
>>> But it does not seem t work because after a static dlopen, _dl_open_hook is NULL.
>>
>> Just to be clear, you have verified that the value of _dl_open_hook is NULL
>> for the copy of that variable in the newly loaded library?
>
> I thought I had. I'm no longer sure. The test case passes now. I
> probably had botched something along the way.
>
> __libc_multiple_libcs is 0, though (although gdb prints 1 because it
> uses the variable in the outer namespace).
That's unfortunate. I would have expected gdb to know the shared library
it is loaded in and use that link map to find the inner value. Did you
inspect the value of __libc_multiple_libcs while executing code inside
the the inner-most libc?
> We have a larger problem, though:
>
> (gdb) info symb &_dl_open_hook
> _dl_open_hook in section .bss of /lib64/libc.so.6
> (This is from a regular dynamically linked executable.)
> This pointer variable should really be in the .relro section.
Agreed.
> The existing patching mechanism for static dlopen uses a dlsym lookup
> in the new namespace, and just patches in the intended value (with
> _dl_open_hook and _dlfcn_hook). It would be nice to have these
> pointers in .relro instead, but that needs significant changes. With
> the current approach, it seems that the patching happens really late,
> after ELF constructors from the new DSOs have already run.
Yes, the calls to __libc_register_* happen last in __dlopen.
I can't think of any strong reason it happens last, other than it was
simple enough to add the calls to __dlopen after you had the link map
(and after you knew dlopen succeeded).
To put it in RELRO you would need to push the calls to
__libc_register_dl_open_hook, and __libc_register_dlfcn_hook into the
callee past the point at which you have a linkmap setup and ready to
use, modify the variables, and then let RELRO finish marking it
read-only.
> Does the above seem more reasonable? (I'm apparently quite confused today.)
Yes.
> As a stop-gap measure, we could mangle the hook pointers. The pointer
> guard value is derived from AT_RANDOM on both sides of the linking
> barrier, so the mangling will be identical.
Agreed.
--
Cheers,
Carlos.