Skip to content

Commit 7e0b172

Browse files
committed
Merge tag 'objtool-urgent-2026-02-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull objtool fixes from Ingo Molnar:: - Bump up the Clang minimum version requirements for livepatch builds, due to Clang assembler section handling bugs causing silent miscompilations - Strip livepatching symbol artifacts from non-livepatch modules - Fix livepatch build warnings when certain Clang LTO options are enabled - Fix livepatch build error when CONFIG_MEM_ALLOC_PROFILING_DEBUG=y * tag 'objtool-urgent-2026-02-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: objtool/klp: Fix unexported static call key access for manually built livepatch modules objtool/klp: Fix symbol correlation for orphaned local symbols livepatch: Free klp_{object,func}_ext data after initialization livepatch: Fix having __klp_objects relics in non-livepatch modules livepatch/klp-build: Require Clang assembler >= 20
2 parents 2687c84 + f495054 commit 7e0b172

8 files changed

Lines changed: 79 additions & 31 deletions

File tree

include/linux/livepatch.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ int klp_enable_patch(struct klp_patch *);
175175
int klp_module_coming(struct module *mod);
176176
void klp_module_going(struct module *mod);
177177

178+
void *klp_find_section_by_name(const struct module *mod, const char *name,
179+
size_t *sec_size);
180+
178181
void klp_copy_process(struct task_struct *child);
179182
void klp_update_patch_state(struct task_struct *task);
180183

kernel/livepatch/core.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,25 @@ void klp_module_going(struct module *mod)
13561356
mutex_unlock(&klp_mutex);
13571357
}
13581358

1359+
void *klp_find_section_by_name(const struct module *mod, const char *name,
1360+
size_t *sec_size)
1361+
{
1362+
struct klp_modinfo *info = mod->klp_info;
1363+
1364+
for (int i = 1; i < info->hdr.e_shnum; i++) {
1365+
Elf_Shdr *shdr = &info->sechdrs[i];
1366+
1367+
if (!strcmp(info->secstrings + shdr->sh_name, name)) {
1368+
*sec_size = shdr->sh_size;
1369+
return (void *)shdr->sh_addr;
1370+
}
1371+
}
1372+
1373+
*sec_size = 0;
1374+
return NULL;
1375+
}
1376+
EXPORT_SYMBOL_GPL(klp_find_section_by_name);
1377+
13591378
static int __init klp_init(void)
13601379
{
13611380
klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj);

scripts/livepatch/init.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
#include <linux/slab.h>
1010
#include <linux/livepatch.h>
1111

12-
extern struct klp_object_ext __start_klp_objects[];
13-
extern struct klp_object_ext __stop_klp_objects[];
14-
1512
static struct klp_patch *patch;
1613

1714
static int __init livepatch_mod_init(void)
1815
{
16+
struct klp_object_ext *obj_exts;
17+
size_t obj_exts_sec_size;
1918
struct klp_object *objs;
2019
unsigned int nr_objs;
2120
int ret;
2221

23-
nr_objs = __stop_klp_objects - __start_klp_objects;
24-
22+
obj_exts = klp_find_section_by_name(THIS_MODULE, ".init.klp_objects",
23+
&obj_exts_sec_size);
24+
nr_objs = obj_exts_sec_size / sizeof(*obj_exts);
2525
if (!nr_objs) {
2626
pr_err("nothing to patch!\n");
2727
ret = -EINVAL;
@@ -41,7 +41,7 @@ static int __init livepatch_mod_init(void)
4141
}
4242

4343
for (int i = 0; i < nr_objs; i++) {
44-
struct klp_object_ext *obj_ext = __start_klp_objects + i;
44+
struct klp_object_ext *obj_ext = obj_exts + i;
4545
struct klp_func_ext *funcs_ext = obj_ext->funcs;
4646
unsigned int nr_funcs = obj_ext->nr_funcs;
4747
struct klp_func *funcs = objs[i].funcs;
@@ -90,12 +90,10 @@ static int __init livepatch_mod_init(void)
9090

9191
static void __exit livepatch_mod_exit(void)
9292
{
93-
unsigned int nr_objs;
94-
95-
nr_objs = __stop_klp_objects - __start_klp_objects;
93+
struct klp_object *obj;
9694

97-
for (int i = 0; i < nr_objs; i++)
98-
kfree(patch->objs[i].funcs);
95+
klp_for_each_object_static(patch, obj)
96+
kfree(obj->funcs);
9997

10098
kfree(patch->objs);
10199
kfree(patch);

scripts/livepatch/klp-build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ validate_config() {
249249
[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] && \
250250
die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
251251

252+
[[ -v CONFIG_AS_IS_LLVM ]] && \
253+
[[ "$CONFIG_AS_VERSION" -lt 200000 ]] && \
254+
die "Clang assembler version < 20 not supported"
255+
252256
return 0
253257
}
254258

scripts/module.lds.S

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,8 @@ SECTIONS {
3434

3535
__patchable_function_entries : { *(__patchable_function_entries) }
3636

37-
__klp_funcs 0: ALIGN(8) { KEEP(*(__klp_funcs)) }
38-
39-
__klp_objects 0: ALIGN(8) {
40-
__start_klp_objects = .;
41-
KEEP(*(__klp_objects))
42-
__stop_klp_objects = .;
43-
}
37+
.init.klp_funcs 0 : ALIGN(8) { KEEP(*(.init.klp_funcs)) }
38+
.init.klp_objects 0 : ALIGN(8) { KEEP(*(.init.klp_objects)) }
4439

4540
#ifdef CONFIG_ARCH_USES_CFI_TRAPS
4641
__kcfi_traps : { KEEP(*(.kcfi_traps)) }

tools/objtool/check.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ static int create_static_call_sections(struct objtool_file *file)
683683

684684
key_sym = find_symbol_by_name(file->elf, tmp);
685685
if (!key_sym) {
686-
if (!opts.module || file->klp) {
686+
if (!opts.module) {
687687
ERROR("static_call: can't find static_call_key symbol: %s", tmp);
688688
return -1;
689689
}
@@ -4762,7 +4762,7 @@ static int validate_ibt(struct objtool_file *file)
47624762
!strcmp(sec->name, "__bug_table") ||
47634763
!strcmp(sec->name, "__ex_table") ||
47644764
!strcmp(sec->name, "__jump_table") ||
4765-
!strcmp(sec->name, "__klp_funcs") ||
4765+
!strcmp(sec->name, ".init.klp_funcs") ||
47664766
!strcmp(sec->name, "__mcount_loc") ||
47674767
!strcmp(sec->name, ".llvm.call-graph-profile") ||
47684768
!strcmp(sec->name, ".llvm_bb_addr_map") ||

tools/objtool/include/objtool/klp.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
#define SHN_LIVEPATCH 0xff20
77

88
/*
9-
* __klp_objects and __klp_funcs are created by klp diff and used by the patch
10-
* module init code to build the klp_patch, klp_object and klp_func structs
11-
* needed by the livepatch API.
9+
* .init.klp_objects and .init.klp_funcs are created by klp diff and used by the
10+
* patch module init code to build the klp_patch, klp_object and klp_func
11+
* structs needed by the livepatch API.
1212
*/
13-
#define KLP_OBJECTS_SEC "__klp_objects"
14-
#define KLP_FUNCS_SEC "__klp_funcs"
13+
#define KLP_OBJECTS_SEC ".init.klp_objects"
14+
#define KLP_FUNCS_SEC ".init.klp_funcs"
1515

1616
/*
1717
* __klp_relocs is an intermediate section which are created by klp diff and

tools/objtool/klp-diff.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,40 @@ static int correlate_symbols(struct elfs *e)
364364
struct symbol *file1_sym, *file2_sym;
365365
struct symbol *sym1, *sym2;
366366

367-
/* Correlate locals */
368-
for (file1_sym = first_file_symbol(e->orig),
369-
file2_sym = first_file_symbol(e->patched); ;
370-
file1_sym = next_file_symbol(e->orig, file1_sym),
371-
file2_sym = next_file_symbol(e->patched, file2_sym)) {
367+
file1_sym = first_file_symbol(e->orig);
368+
file2_sym = first_file_symbol(e->patched);
369+
370+
/*
371+
* Correlate any locals before the first FILE symbol. This has been
372+
* seen when LTO inexplicably strips the initramfs_data.o FILE symbol
373+
* due to the file only containing data and no code.
374+
*/
375+
for_each_sym(e->orig, sym1) {
376+
if (sym1 == file1_sym || !is_local_sym(sym1))
377+
break;
378+
379+
if (dont_correlate(sym1))
380+
continue;
381+
382+
for_each_sym(e->patched, sym2) {
383+
if (sym2 == file2_sym || !is_local_sym(sym2))
384+
break;
385+
386+
if (sym2->twin || dont_correlate(sym2))
387+
continue;
388+
389+
if (strcmp(sym1->demangled_name, sym2->demangled_name))
390+
continue;
391+
392+
sym1->twin = sym2;
393+
sym2->twin = sym1;
394+
break;
395+
}
396+
}
397+
398+
/* Correlate locals after the first FILE symbol */
399+
for (; ; file1_sym = next_file_symbol(e->orig, file1_sym),
400+
file2_sym = next_file_symbol(e->patched, file2_sym)) {
372401

373402
if (!file1_sym && file2_sym) {
374403
ERROR("FILE symbol mismatch: NULL != %s", file2_sym->name);
@@ -1436,7 +1465,7 @@ static int clone_special_sections(struct elfs *e)
14361465
}
14371466

14381467
/*
1439-
* Create __klp_objects and __klp_funcs sections which are intermediate
1468+
* Create .init.klp_objects and .init.klp_funcs sections which are intermediate
14401469
* sections provided as input to the patch module's init code for building the
14411470
* klp_patch, klp_object and klp_func structs for the livepatch API.
14421471
*/

0 commit comments

Comments
 (0)