Is your feature request related to a problem? Please describe.
We are developing a Rust-based KernelPatch module (KPM) that utilizes the Rust formatting system (core::fmt).
When compiling a Rust module using the official precompiled core library (which defaults to PIC for compatibility), the compiler generates GOT relocations (such as R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC) for global symbols used by core::fmt.
Currently, the KernelPatch loader throws an unsupported RELA relocation error (returning -ENOEXEC for relocation types 310, 311, 312) because it does not support GOT-related relocations.
Describe the solution you'd like
It would be highly beneficial if the KernelPatch module loader supported GOT-related relocations on ARM64, specifically:
R_AARCH64_LD64_GOTOFF_LO15 (310)
R_AARCH64_ADR_GOT_PAGE (311)
R_AARCH64_LD64_GOT_LO12_NC (312)
This could be achieved by allocating a Global Offset Table (GOT) dynamically for the loaded module and populating it with resolved symbol addresses, or by utilizing dynamic instruction rewriting (e.g., rewriting the LDR instruction of R_AARCH64_LD64_GOT_LO12_NC to an ADD instruction to bypass the GOT reference entirely).
Describe alternatives you've considered
- Recompiling
core with build-std:
We can recompile the Rust standard library (core) without PIC by using -Z build-std and -C relocation-model=static. This prevents the compiler from generating GOT relocations in the first place. However, this requires Rust nightly and increases build times significantly.
- Direct mapping in loader (not fully safe):
We can locally define the GOT relocations and map them to absolute relocations in the loader. However, without allocating a real GOT or rewriting the instruction from ldr to add, the ldr instruction will load the contents at the symbol address instead of the address itself, which can lead to unexpected behaviors or crashes depending on the symbol type.
Additional context
Below are the changes we experimented with in the loader to bypass the unsupported relocation errors:
In kernel/linux/arch/arm64/include/asm/elf.h:
#define R_AARCH64_LD64_GOTOFF_LO15 310
#define R_AARCH64_ADR_GOT_PAGE 311
#define R_AARCH64_LD64_GOT_LO12_NC 312
In kernel/patch/module/relo.c:
/* GOT relocations - treat GOT symbols as absolute addresses */
case R_AARCH64_ADR_GOT_PAGE: /* 0x137 = 311 */
ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21, AARCH64_INSN_IMM_ADR);
break;
case R_AARCH64_LD64_GOT_LO12_NC: /* 0x138 = 312 */
overflow_check = false;
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9, AARCH64_INSN_IMM_12);
break;
case R_AARCH64_LD64_GOTOFF_LO15: /* 0x136 = 310 */
overflow_check = false;
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 12, AARCH64_INSN_IMM_12);
break;
Is your feature request related to a problem? Please describe.
We are developing a Rust-based KernelPatch module (KPM) that utilizes the Rust formatting system (
core::fmt).When compiling a Rust module using the official precompiled
corelibrary (which defaults to PIC for compatibility), the compiler generates GOT relocations (such asR_AARCH64_ADR_GOT_PAGEandR_AARCH64_LD64_GOT_LO12_NC) for global symbols used bycore::fmt.Currently, the KernelPatch loader throws an
unsupported RELA relocationerror (returning-ENOEXECfor relocation types 310, 311, 312) because it does not support GOT-related relocations.Describe the solution you'd like
It would be highly beneficial if the KernelPatch module loader supported GOT-related relocations on ARM64, specifically:
R_AARCH64_LD64_GOTOFF_LO15(310)R_AARCH64_ADR_GOT_PAGE(311)R_AARCH64_LD64_GOT_LO12_NC(312)This could be achieved by allocating a Global Offset Table (GOT) dynamically for the loaded module and populating it with resolved symbol addresses, or by utilizing dynamic instruction rewriting (e.g., rewriting the
LDRinstruction ofR_AARCH64_LD64_GOT_LO12_NCto anADDinstruction to bypass the GOT reference entirely).Describe alternatives you've considered
corewithbuild-std:We can recompile the Rust standard library (
core) without PIC by using-Z build-stdand-C relocation-model=static. This prevents the compiler from generating GOT relocations in the first place. However, this requires Rust nightly and increases build times significantly.We can locally define the GOT relocations and map them to absolute relocations in the loader. However, without allocating a real GOT or rewriting the instruction from
ldrtoadd, theldrinstruction will load the contents at the symbol address instead of the address itself, which can lead to unexpected behaviors or crashes depending on the symbol type.Additional context
Below are the changes we experimented with in the loader to bypass the unsupported relocation errors:
In
kernel/linux/arch/arm64/include/asm/elf.h:In
kernel/patch/module/relo.c: