Misc objtool fixes:

- 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.
 
 Signed-off-by: Ingo Molnar <mingo@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmmHCvwRHG1pbmdvQGtl
 cm5lbC5vcmcACgkQEnMQ0APhK1hkTQ/8DhLI5m9CqhMaouuR5Vm9POKgFOXAe6uz
 eHTuKhpJlw+anhNjeUA7PtYbnkrj0j+aNo5SmrfD4Yx8CW7dCt+oO3Y5ziVhkPHw
 46Q/9KbmcT11uPbYywp/G4b15FF8YYu9slzhGau/Wa9H+oqU/WPoGapJsMPpUtBo
 s0qGxdr2G3WZyD9H/wgCyhMwCOkAYMJ0sHxpGgRajLefDutsRvtlau/ktYU79vI3
 nUFteD3YDIAUblBtZPogsCP36QJlx7TWCUNK02vPeOYRh3xPjf3iG+vgf1+sjZHV
 P20psekpDwhh1KyeVziUyihUy8TmEVVozRvsrUKVlXmEqLqDtNrysqKTSp5/yRdT
 MqgNwDrvv2wW/DKYJhefbuttx3ppAErrnJ3zC9TYSmdn27feKPDJcD1OmdS3BIpH
 x9u/eVbOS8xbsOc/t3/Al7CRazvjLU0+OXsMJWbmAaO3tE7SwHq2aOnGbLGjvwWC
 Ts1AYfNp4H41CLLFnmKR8q2t/DOBhefW8p3cR5U+cVQ7PdqKRT+TwKWVnCrbrBcJ
 71702IrqoghwUrmhtxdZR0jZLtwb80s8zqdbrHojXSbXUFfYwwHNNaW1NSEpdSr4
 W8xYfSPrK71OGZ6oh/v1Wce6D+mxqb6kYD8DRLgOdbxrnvLwUhGXxxNDjfXA0f4B
 abjGHlAyoCs=
 =cdu2
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2026-02-07 08:21:21 -08:00
commit 7e0b172c80
8 changed files with 79 additions and 31 deletions

View file

@ -175,6 +175,9 @@ int klp_enable_patch(struct klp_patch *);
int klp_module_coming(struct module *mod);
void klp_module_going(struct module *mod);
void *klp_find_section_by_name(const struct module *mod, const char *name,
size_t *sec_size);
void klp_copy_process(struct task_struct *child);
void klp_update_patch_state(struct task_struct *task);

View file

@ -1356,6 +1356,25 @@ void klp_module_going(struct module *mod)
mutex_unlock(&klp_mutex);
}
void *klp_find_section_by_name(const struct module *mod, const char *name,
size_t *sec_size)
{
struct klp_modinfo *info = mod->klp_info;
for (int i = 1; i < info->hdr.e_shnum; i++) {
Elf_Shdr *shdr = &info->sechdrs[i];
if (!strcmp(info->secstrings + shdr->sh_name, name)) {
*sec_size = shdr->sh_size;
return (void *)shdr->sh_addr;
}
}
*sec_size = 0;
return NULL;
}
EXPORT_SYMBOL_GPL(klp_find_section_by_name);
static int __init klp_init(void)
{
klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj);

View file

@ -9,19 +9,19 @@
#include <linux/slab.h>
#include <linux/livepatch.h>
extern struct klp_object_ext __start_klp_objects[];
extern struct klp_object_ext __stop_klp_objects[];
static struct klp_patch *patch;
static int __init livepatch_mod_init(void)
{
struct klp_object_ext *obj_exts;
size_t obj_exts_sec_size;
struct klp_object *objs;
unsigned int nr_objs;
int ret;
nr_objs = __stop_klp_objects - __start_klp_objects;
obj_exts = klp_find_section_by_name(THIS_MODULE, ".init.klp_objects",
&obj_exts_sec_size);
nr_objs = obj_exts_sec_size / sizeof(*obj_exts);
if (!nr_objs) {
pr_err("nothing to patch!\n");
ret = -EINVAL;
@ -41,7 +41,7 @@ static int __init livepatch_mod_init(void)
}
for (int i = 0; i < nr_objs; i++) {
struct klp_object_ext *obj_ext = __start_klp_objects + i;
struct klp_object_ext *obj_ext = obj_exts + i;
struct klp_func_ext *funcs_ext = obj_ext->funcs;
unsigned int nr_funcs = obj_ext->nr_funcs;
struct klp_func *funcs = objs[i].funcs;
@ -90,12 +90,10 @@ err:
static void __exit livepatch_mod_exit(void)
{
unsigned int nr_objs;
struct klp_object *obj;
nr_objs = __stop_klp_objects - __start_klp_objects;
for (int i = 0; i < nr_objs; i++)
kfree(patch->objs[i].funcs);
klp_for_each_object_static(patch, obj)
kfree(obj->funcs);
kfree(patch->objs);
kfree(patch);

View file

@ -249,6 +249,10 @@ validate_config() {
[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] && \
die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
[[ -v CONFIG_AS_IS_LLVM ]] && \
[[ "$CONFIG_AS_VERSION" -lt 200000 ]] && \
die "Clang assembler version < 20 not supported"
return 0
}

View file

@ -34,13 +34,8 @@ SECTIONS {
__patchable_function_entries : { *(__patchable_function_entries) }
__klp_funcs 0: ALIGN(8) { KEEP(*(__klp_funcs)) }
__klp_objects 0: ALIGN(8) {
__start_klp_objects = .;
KEEP(*(__klp_objects))
__stop_klp_objects = .;
}
.init.klp_funcs 0 : ALIGN(8) { KEEP(*(.init.klp_funcs)) }
.init.klp_objects 0 : ALIGN(8) { KEEP(*(.init.klp_objects)) }
#ifdef CONFIG_ARCH_USES_CFI_TRAPS
__kcfi_traps : { KEEP(*(.kcfi_traps)) }

View file

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

View file

@ -6,12 +6,12 @@
#define SHN_LIVEPATCH 0xff20
/*
* __klp_objects and __klp_funcs are created by klp diff and used by the patch
* module init code to build the klp_patch, klp_object and klp_func structs
* needed by the livepatch API.
* .init.klp_objects and .init.klp_funcs are created by klp diff and used by the
* patch module init code to build the klp_patch, klp_object and klp_func
* structs needed by the livepatch API.
*/
#define KLP_OBJECTS_SEC "__klp_objects"
#define KLP_FUNCS_SEC "__klp_funcs"
#define KLP_OBJECTS_SEC ".init.klp_objects"
#define KLP_FUNCS_SEC ".init.klp_funcs"
/*
* __klp_relocs is an intermediate section which are created by klp diff and

View file

@ -364,11 +364,40 @@ static int correlate_symbols(struct elfs *e)
struct symbol *file1_sym, *file2_sym;
struct symbol *sym1, *sym2;
/* Correlate locals */
for (file1_sym = first_file_symbol(e->orig),
file2_sym = first_file_symbol(e->patched); ;
file1_sym = next_file_symbol(e->orig, file1_sym),
file2_sym = next_file_symbol(e->patched, file2_sym)) {
file1_sym = first_file_symbol(e->orig);
file2_sym = first_file_symbol(e->patched);
/*
* Correlate any locals before the first FILE symbol. This has been
* seen when LTO inexplicably strips the initramfs_data.o FILE symbol
* due to the file only containing data and no code.
*/
for_each_sym(e->orig, sym1) {
if (sym1 == file1_sym || !is_local_sym(sym1))
break;
if (dont_correlate(sym1))
continue;
for_each_sym(e->patched, sym2) {
if (sym2 == file2_sym || !is_local_sym(sym2))
break;
if (sym2->twin || dont_correlate(sym2))
continue;
if (strcmp(sym1->demangled_name, sym2->demangled_name))
continue;
sym1->twin = sym2;
sym2->twin = sym1;
break;
}
}
/* Correlate locals after the first FILE symbol */
for (; ; file1_sym = next_file_symbol(e->orig, file1_sym),
file2_sym = next_file_symbol(e->patched, file2_sym)) {
if (!file1_sym && file2_sym) {
ERROR("FILE symbol mismatch: NULL != %s", file2_sym->name);
@ -1436,7 +1465,7 @@ static int clone_special_sections(struct elfs *e)
}
/*
* Create __klp_objects and __klp_funcs sections which are intermediate
* Create .init.klp_objects and .init.klp_funcs sections which are intermediate
* sections provided as input to the patch module's init code for building the
* klp_patch, klp_object and klp_func structs for the livepatch API.
*/