Skip to content
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

Symbol interposition support for .bss data within a patch. #1

Closed
elfmaster opened this issue Dec 8, 2022 · 2 comments
Closed

Symbol interposition support for .bss data within a patch. #1

elfmaster opened this issue Dec 8, 2022 · 2 comments
Assignees
Labels
bug Something isn't working enhancement New feature or request

Comments

@elfmaster
Copy link
Contributor

elfmaster commented Dec 8, 2022

Feature Description

In the original Shiva implementaiton we didn't include proper support for transforming the uninitialized variable data from an ET_REL object into the .bss area setup in memory by the Shiva module loader.

Details

A Shiva patch module can now properly load and store from .bss variables, however the external linking to patch the executable so that it references an interposed .bss variable will fail.

ELF relocatable objects store .bss variables as STT_OBJECT/STB_GLOBAL as is common with static data, but it has a symbol->st_shndx value of SHN_COMMON, which means this global symbol is apart of a common block of uninitialized data

Furthermore the symbol->st_value, as it pertains to ELF ET_REL files, will not contain the offset of the .bss variable. Instead it contains the size of the variable, which is reduntant since symbol->st_size already gives us the size. The size of each variable is enough for us to calculate the offsets necessary to store them in a memory mapped .bss area within the patch module.

Partially fixed as of 12/8/22

ELF program we are patching: modules/patches/symbol_interposing4/test_function_patch
patch object: modules/patches/symbol_interposing4/fpatch4.o

The patch replaces function foo() and writes a different value to the int bss_var;

When foo() prints bss_var the value is 31337. Which is correct, however the XREF from bar() to bss_var is not inserted.
We don't yet support the external linking code to identify the XREF, therefore bar() still references the original bss_var.

Support for indirect XREF's (i.e. via GOT)

We do not support this:

adrp        x0, <segment_offset> ; get page aligned address of text + segment_offset
ldr           x0, [x0, #pgoff] ; retrieve the address of the .bss variable from the .got
ldr           w1, [x0] ; load the .bss variable from memory into w1

Or the relaxed version of the code.... (i.e. no code relaxation)

adrp        x0, <segment_offset> ; get page aligned address of text + segment_offset
add         x0, x0, #pgoff ; retrieve the address of the .bss variable from the .got
ldr           x0, [x0] ; retrieve the address of the .bss variable from the .got
ldr           w1, [x0] ; load the .bss variable from memory into w1

R_AARCH64_RELATIVE relocations and linker chaining in PIE executable

The xref instruction sequences above access a given variable, such as one in the .bss, by indirectly accessing it. The address to the variable is stored in a read-only table at the end of the function, within the .text section. At runtime the ld-linux.so applies the symbol value of bss_var to the base address of the executabe, and patches the read-only table with this value. This read-only table can be referenced for indirect variable access.

The solution, therefore, is for Shiva to modify the rela.dyn relocation entries that patches various parts of .the .text section with the address to the variable we are patching and thus re-linking.

We search for the rela.dyn entry of type R_AARCH64_RELATIVE that has an r_addend value that is equal to the symbol value of the variable we are patching within the executable. i.e. if symbol bss_var had an address of 0x11014 then we'd search for the relative relocation's who's r_addend is that value.

We would then modify the r_addend to be the negative offset from <base_of_executable> to the bss_var value.
i.e. if bss_var is at 0x6001014, and the base of the executable is 0x8000000. We would compute:

delta = 0x8000000 - 0x6001014
new_r_addend = -delta

At runtime Shiva patches the correct relative relocations as shown in the psuedo-code snippet above. As a result the ld-linux.so RTLD will patch relocation unit with the correct offset to the bss_var that exists in the loaded patch.

This is a great example of Cross relocation

@elfmaster elfmaster self-assigned this Dec 8, 2022
@elfmaster elfmaster added bug Something isn't working enhancement New feature or request labels Dec 8, 2022
@elfmaster
Copy link
Contributor Author

Finished. We successfully update the relocation record that will patch the indirect xref for us via ld-linux rtld.

Essentially Shiva manipulates the hot-patching behavior of ld-linux.so by updating certain rela.dyn relocation records that are necessary to re-link xrefs to patched variables.

@elfmaster
Copy link
Contributor Author

Indirect xrefs are now linked for .bss variables. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant