-
-
Notifications
You must be signed in to change notification settings - Fork 493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
patchelf 0.10 corrupts some shared libraries #170
Comments
In case it's relevant, this shared library was previously patched using |
There is a comment about a similar bug here: #158 (comment) |
In this case, rebuilding this binary package using |
I had to abort switching patchelf default from 0.9 to 0.10 in nixpkgs due to some corruptions like this. Example I studied:
When I look at binary diff (via Switching the default rebuilds everything, so it's a bit difficult to play with that, but fortunately it's enough to trigger the bug by overrides like above. Just in case, cache.nixos.org now does have almost full binary set for nixpkgs with patchelf 0.10, e.g. commit NixOS/nixpkgs@2c3dcbb https://hydra.nixos.org/eval/1543924 – might be useful. |
One doable thing is to bisect the above test over patchelf versions – that should be relatively fast, and it might help to narrow down the problem. |
This issue has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/why-is-nixos-patchelf-still-at-0-9/6006/2 |
Offending commit is c4deb5e, according to #192 (comment) Stripping after patchelfing was one of the main reasons why 0.10 was released. |
The current approach to changing sections in ET_DYN executables is to move the INTERP section to the end of the file. +This means changing PT_PHDR to add an extra PT_LOAD section so that the new section is mmaped into memory by the elf loader in the kernel. In order to extend PHDR, this means moving it to the end of the file. Its documented in BUGS there is a kernel 'bug' which means that if you have holes in memory between the base load address and the PT_LOAD segment that contains PHDR, it will pass an incorrect PHDR address to ld.so and fail to load the binary, segfaulting. To avoid this, the code currently inserts space into the binary to ensure that when loaded into memory there are no holes between the PT_LOAD sections. This inflates the binaries by many MBs in some cases. Whilst we could make them sparse, there is a second issue which is that strip can fail to process these binaries: $ strip fixincl Not enough room for program headers, try linking with -N [.note.ABI-tag]: Bad value This turns out to be due to libbfd not liking the relocated PHDR section either (#10). Instead this patch implements a different approach, leaving PHDR where it is but extending it in place to allow addition of a new PT_LOAD section. This overwrites sections in the binary but those get moved to the end of the file in the new PT_LOAD section. This is based on patches linked from the above github issue, however whilst the idea was good, the implementation wasn't correct and they've been rewritten here. Signed-off-by: Richard Purdie <[email protected]>
From the output of objdump -x on this library, the top of the .dynamic section is getting trashed: 0x600000001 0x0000000000429000 and with some debugging its the PT_LOAD section injection which does it. That code starts with the comment: I've run out of time to figure out why the PT_LOAD section is clobbering .dynamic today but its at least a good start at figuring out the problem. |
Tracked down a possible fix which is adding: The issue is that if the program headers were previously relocated to the end of the file, this new code assumes they're located after the elf header. The above line forces them back there which is where the code has made space for them. I can sort out a proper patch/pull request in due course but thought I'd at least post this now since I found a potential fix. It explains why Yocto Project doesn't see this since we tend only to edit newly compiled binaries. |
Do you think it's already ripe for firing a Hydra.nixos.org jobset to test this on whole NixPkgs? (say, x86_64 only) I haven't tried to really understand this issue so far. |
When running patchelf on some existing patchelf'd binaries to change to longer RPATHS, ldd would report the binaries as invalid. The output of objdump -x on those libraryies should show the top of the .dynamic section is getting trashed, something like: 0x600000001 0x0000000000429000 0x335000 0x0000000000335000 0xc740 0x000000000000c740 0x1000 0x0000000000009098 SONAME libglib-2.0.so.0 (which should be RPATH and DT_NEEDED entries) This was tracked down to the code which injects the PT_LOAD section. The issue is that if the program headers were previously relocated to the end of the file which was how patchelf operated previously, the relocation code wouldn't work properly on a second run as it now assumes they're located after the elf header. This change forces them back to immediately follow the elf header which is where the code has made space for them. Should fix NixOS#170 and NixOS#192 Signed-off-by: Richard Purdie <[email protected]>
After using
patchelf
0.10 to patch a shared library, ldd reportsInconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != NULL' failed!
.Steps to reproduce:
The text was updated successfully, but these errors were encountered: