mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
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:
commit
7e0b172c80
8 changed files with 79 additions and 31 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)) }
|
||||
|
|
|
|||
|
|
@ -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") ||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue