I am implementing "function granular kernel address space layout randomization" for Linux, and am trying to solve a problem that I am really hoping there is a compiler or linker option for. My implementation uses gcc's -ffunction-sections to break apart the kernel .text section by function. At kernel boot time, just after decompression, I shuffle all the function sections randomly and re-layout the kernel. Surprisingly, this works pretty well, but I am having a problem with a niche condition that is important to resolve for the live-patching use case. In order to live-patch the kernel, the live-patching code will request the address of symbols by name from the kernel. This works great after randomization because it always receives the current address at runtime rather than relying on any kind of buildtime address. The issue with with the live-patching code's algorithm for resolving duplicate symbol names. If they request a symbol by name from the kernel and there are 3 symbols with the same name, they use the symbol's position in the built binary image to select the correct symbol. This is obviously invalid when the layout has been shuffled randomly. I was hoping there was some kind of compiler or linker option that would add some kind of uniqueness to the symbols to make sure their were never any duplicates, but I am not finding such a thing. Is there something like this already available? Thanks very much!
Please try https://gitlab.com/x86-binutils/binutils-gdb/-/tree/users/hjl/pr26391/master You can pass -z unique to ld to make local symbols unique.
This works for me! Thanks!
I updated my branch to rename the option name to "-z unique-symbol".
This feature was well received by the livepatch maintainers. It not only solves my individual problem, but also would allow them to more precisely locate duplicate symbols in general for patching. I'd like to request that this feature be implemented in a future release.
https://lore.kernel.org/live-patching/4dc070f53f4f96b47dba4e4e51bb65d75f2071bb.camel@linux.intel.com/T/#mb29f61d93a1f0307212053c90ab86cb9fe5a64ee
A patch is posted at https://sourceware.org/pipermail/binutils/2020-September/113271.html
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=496afd17055aeb7d8f45e01715c475664f2b73bd commit 496afd17055aeb7d8f45e01715c475664f2b73bd Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Sep 12 05:37:30 2020 -0700 elf: Add -z unique-symbol to avoid duplicated local symbol names The symbol string table in the .symtab section is optional and cosmetic. The contents of the .symtab section have no impact on run-time execution. The symbol names in the symbol string table help distinguish addresses at different locations. Add a linker option, -z unique-symbol, to avoid duplicated local symbol names in the symbol string table. This feature was well received by the livepatch maintainers. It not only solves the duplicated local symbol name problem, but also would allow livepatch to more precisely locate duplicate symbols in general for patching. bfd/ PR ld/26391 * elflink.c (elf_final_link_info): Add local_hash_table. (local_hash_entry): New. (local_hash_newfunc): Likewise. (elf_link_output_symstrtab): Append ".COUNT" to duplicated local symbols. (bfd_elf_final_link): Initialize and free local_hash_table for "-z unique-symbol". include/ PR ld/26391 * bfdlink.h (bfd_link_info): Add unique_symbol. ld/ PR ld/26391 * NEWS: Mention "-z unique-symbol". * emultempl/elf.em (gld${EMULATION_NAME}_handle_option): Handle "-z unique-symbol" and "-z nounique-symbol". * ld.texi: Document "-z unique-symbol" and "-z nounique-symbol". * lexsup.c (elf_static_list_options): Add "-z unique-symbol" and "-z nounique-symbol". * testsuite/ld-elf/elf.exp: Add PR ld/26391 tests. * testsuite/ld-elf/pr26391.nd: New file. * testsuite/ld-elf/pr26391.out: Likewise. * testsuite/ld-elf/pr26391a.c: Likewise. * testsuite/ld-elf/pr26391b.c: Likewise. * testsuite/ld-elf/pr26391c.c: Likewise. * testsuite/ld-elf/pr26391d.c: Likewise.
Fixed for 2.36.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1f656a652ea8d489b5aa5b7f55c535fc9e6b0b29 commit 1f656a652ea8d489b5aa5b7f55c535fc9e6b0b29 Author: Alan Modra <amodra@gmail.com> Date: Sun Sep 13 17:56:52 2020 +0930 Re: elf: Add -z unique-symbol PR 26391 * testsuite/ld-elf/pr26391.nd: Adjust to match powerpc64 function descriptors.
It seems that this test is failing on sparc64: FAIL: Run pr26391-5 FAIL: Run pr26391-6 See: https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=sparc64&ver=2.37-10&stamp=1637614637&raw=0
(In reply to John Paul Adrian Glaubitz from comment #10) > It seems that this test is failing on sparc64: > > FAIL: Run pr26391-5 > FAIL: Run pr26391-6 > > See: > https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=sparc64&ver=2. > 37-10&stamp=1637614637&raw=0 I have verified that this commit introduced the regression on sparc64: 496afd17055aeb7d8f45e01715c475664f2b73bd is the first bad commit commit 496afd17055aeb7d8f45e01715c475664f2b73bd Author: H.J. Lu <hjl.tools@gmail.com> Date: Sat Sep 12 05:37:30 2020 -0700 elf: Add -z unique-symbol to avoid duplicated local symbol names The symbol string table in the .symtab section is optional and cosmetic. The contents of the .symtab section have no impact on run-time execution. The symbol names in the symbol string table help distinguish addresses at different locations. Add a linker option, -z unique-symbol, to avoid duplicated local symbol names in the symbol string table. This feature was well received by the livepatch maintainers. It not only solves the duplicated local symbol name problem, but also would allow livepatch to more precisely locate duplicate symbols in general for patching.
I don't know why "ld -r -z unique-symbol" generates incorrect output on sparc64.
Created attachment 13877 [details] sparc64-linux binaries I built sparc64-linux pr26391-5 and pr26391-6 binaries with a cross compiler on Linux/x8-64. They run fine on sparc64-linux: hjl@gcc102:~$ cd /tmp/ hjl@gcc102:/tmp$ ./pr26391-5 bar 1 bar 2 bar 3 hjl@gcc102:/tmp$ ./pr26391-6 bar 1 bar 2 bar 3 hjl@gcc102:/tmp$ If they fail in binutils tests on sparc64-linux, it is caused by sparc64-linux hardware, kernel, glibc, binutils, ... bugs.
The try-PR26391 branch has been updated by Mark Wielaard <mark@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=99175c84026b1bfa534f3946150535c39027911d commit 99175c84026b1bfa534f3946150535c39027911d Author: Sam James <sam@gentoo.org> Date: Mon Jan 16 14:03:02 2023 -0800 ld: Use run_cc_link_tests for PR ld/26391 tests Use run_cc_link_tests for PR ld/26391 tests to compile PR ld/26391 tests in C. PR ld/30002 * testsuite/ld-elf/elf.exp: Use run_cc_link_tests for PR ld/26391 tests.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=64b59b6bb2261fe2fa8310f94b4ed420c162e357 commit 64b59b6bb2261fe2fa8310f94b4ed420c162e357 Author: H.J. Lu <hjl.tools@gmail.com> Date: Mon Jan 16 14:03:02 2023 -0800 ld: Use run_cc_link_tests for PR ld/26391 tests Use run_cc_link_tests for PR ld/26391 tests to compile PR ld/26391 tests in C. PR ld/30002 * testsuite/ld-elf/elf.exp: Use run_cc_link_tests for PR ld/26391 tests.