Summary: | ld.so - Initialization and Termination Functions incorrectly ordered | ||
---|---|---|---|
Product: | glibc | Reporter: | George Gensure <werkt0> |
Component: | libc | Assignee: | George Gensure <werkt0> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | drepper.fsp, fweimer, glibc-bugs |
Priority: | P2 | Flags: | fweimer:
security-
|
Version: | 2.11 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: | ||
Attachments: |
Dependency hierarchy which breaks existing deps sorting (apologies for the complexity)
topological sort implementation for dependency resolution Revised fix including test case (case fails independently in the previous implementation of ld.so) Example of post-patch initialization order failure. |
Description
George Gensure
2010-06-18 18:33:23 UTC
Created attachment 4851 [details]
Dependency hierarchy which breaks existing deps sorting (apologies for the complexity)
This is the list of l_initfini in dl-deps.c when the initialization order is
determined which produces incorrect output. I have left in the leader
dependency for each library which points back to itself.
Created attachment 4852 [details]
topological sort implementation for dependency resolution
I've used the implementation of tsort from coreutils here almost verbatim. One
point of contention might be the (long) cast for comparison in dl-tsort.c - if
there's a better portable pointer equiv integer type that will give a negative
value for subtraction (since pointers won't), that will be fine. Obviously
this introduces some recursion into ld.so, and I saw in a comment that that is
not desirable. This implementation works to provide correct init and fini
ordering for everything I've thrown at it.
You'll have to provide a complete small, self-contained test case. Created attachment 4855 [details]
Revised fix including test case (case fails independently in the previous implementation of ld.so)
Test case added to elf/ as tst-initorder, with a comparison test to make sure
that the initialization occurs in order. This is a failure set for the
previous implementation.
I've also done a couple of tweaks to the existing patch, returning instead of
trying to sort if we run out of memory during fini. Technically the previous
implementation could be used if memory allocation fails, since it does not use
any new allocations.
(In reply to comment #2) > there's a better portable pointer equiv integer type int a = (l > p->l) - (l < p->l); (In reply to comment #5) > int a = (l > p->l) - (l < p->l); Fine by me. Do you want an update of the diff for this? I check in your test and a patch I wrote. Created attachment 5872 [details]
Example of post-patch initialization order failure.
Your patch is not sufficient. You corrected the given case, but opened up another failure case. I have attached a reproducer for the failure case. I recommend again that my previous patch be accepted as it was, since it worked for both of these cases. The failure condition now, which did not break under the previous implementation, is described as follows:
main => deps1, deps4, deps3
deps1 => deps2
deps2 => deps3
deps3 => deps4
THis has long since been handled. |