diff --git a/kernel/livepatch/Kconfig b/kernel/livepatch/Kconfig index 239480682c92eda87ee5047c1c7bd2f8e4375b4f..d663ad91c6198a1d4b154feeee2a22603946e65b 100644 --- a/kernel/livepatch/Kconfig +++ b/kernel/livepatch/Kconfig @@ -101,4 +101,14 @@ config LIVEPATCH_ISOLATE_KPROBE do not allow both modify the same instruction when a function is marked as 'notrace' and without the reserved instructions. +config LIVEPATCH_LONG_SYMBOL_SUPPORT + bool "support relocate symbol name whose length longer than 128 bytes" + depends on LIVEPATCH_WO_FTRACE + default y + help + symbols longer than KSYM_NAME_LEN will be truncated in strtab, + we can not find them using original name, so we use a new format + .klp.sym.objname-ref_name,ref_offset to find a unique symbol + and add ref_offset to get the long name symbol address. + endmenu diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 6c5b3f52967ad9f5f4edfcafdbdfbffa087c9a46..cf13fe9d152ff6d2fb94b44de47f36ba779343dd 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -234,6 +234,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, #endif Elf_Sym *sym; unsigned long sympos, addr; + long ref_offset; bool sym_vmlinux; bool sec_vmlinux = !strcmp(sec_objname, "vmlinux"); @@ -267,10 +268,19 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, return -EINVAL; } + ref_offset = 0; /* Format: .klp.sym.sym_objname.sym_name,sympos */ cnt = sscanf(strtab + sym->st_name, ".klp.sym.%55[^.].%511[^,],%lu", sym_objname, sym_name, &sympos); + if (IS_ENABLED(CONFIG_LIVEPATCH_LONG_SYMBOL_SUPPORT) && cnt != 3) { + /* Format: .klp.sym.objname-ref_name,ref_offset*/ + cnt = sscanf(strtab + sym->st_name, + ".klp.sym.%55[^-]-%127[^,],%ld", + sym_objname, sym_name, &ref_offset); + if (cnt == 3) + sympos = 1; + } if (cnt != 3) { pr_err("symbol %s has an incorrectly formatted name\n", strtab + sym->st_name); @@ -298,6 +308,8 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, return ret; sym->st_value = addr; + if (IS_ENABLED(CONFIG_LIVEPATCH_LONG_SYMBOL_SUPPORT)) + sym->st_value += ref_offset; } return 0;