This is the mail archive of the libc-alpha@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]

Re: Removing longjmp error handling from the dynamic loader


* Rich Felker:

> Assuming ifunc resolvers aren't "allowed" to do much beyond probing
> hwcaps/cpuid/etc. to pick an implementation, I don't see any reason
> that resolver failure during an ifunc resolver function should
> terminate the process.

Depending on which documentation you read, IFUNC resolvers must not
depend on run-time relocations themselves.  In that case, lazy binding
failure during execution of an IFUNC resolver cannot possibly happen in
a valid program.

We would also have to disable signals while IFUNC resolvers are running,
so that lazy binding errors in signal handlers do not leak into the
dlopen call (after longjmp'ing out of the signal handler).

Is this really worth the trouble?

> Missing symbols at dlopen time with RTLD_NOW or DT_BINDNOW or whatever
> should never crash the application, but should report the error. With
> ifunc, I think (?) you have the possibility that the ifunc resolver
> code will call another function in the library being loaded (or one of
> its deps) via a plt slot that hasn't yet been initialized, because
> there's no way to know a dependency order for the relocations to avoid
> this.

We perform relocations in topological order, and IRELATIVE relocations
are sorted last by current binutils.  So in the absence of cyclic
dependencies (perhaps as the result of symbol interposition), IFUNC
resolvers will not encounter uninitialized PLT slots.

> This should probably longjmp back and make dlopen fail; I can't see
> any other way to make it work since there's no way to make forward
> progress past the impossible-to-satisfy call.

If you can detect at all that the relocation has not been processed, you
could longjmp out of the IFUNC resolver and try something else, until
there is definitely no way to make progress.  (I'm not saying that this
longjmp is valid, but it is a possibility.)

But I really don't see how we can make this work reliably because there
are relocation dependencies that do not involve lazy binding or PLT
calls, and we cannot detect those.  The IFUNC resolver would just use
uninitialized data or data that is later overwritten.

Two-phase relocation processing in topology order (first all non-IFUNC
relocations, then the IFUNC relocations) seems to cover all the
practical cases involving symbol interposition.  It deals correctly with
glibc's internal uses of those (which can currently lead to crashes, see
bug 21041).  It also covers, by design, all relocations for data symbols
because they cannot involve IFUNCs.  It does not deal with all cases
where an IFUNC resolver uses a function pointer variable that has been
initialized by a relocation, and that value is itself the result of an
IFUNC resolver.  It also cannot support cases where an IFUNC resolver
depends on ELF constructors having run for one of its dependencies
(which some people did, until distributions started building with
BIND_NOW).

> But maybe the relocations can just be ordered such that this isn't a
> concern (by checking all symbolic references prior to doing any ifunc
> resolvers?).

I think doing that would be excessive and it wouldn't cover the case
where the IFUNC resolver actually relies on lazy binding for choosing
the implementation (which could be constructed as valid if IFUNC
resolvers may rely on relocations).

>> If we want to give users more precise control over binding errors, I
>> don't think anything based on SJLJ-style exception handling is the
>> answer.
>
> I don't see why there should be any expectation that you can use C++
> exception handling for this; the contract of dlopen is that it succeed
> or return an error, not that it might terminate via an exception.

I meant for a call that results in a lazy binding failure.

Thanks,
Florian


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