Skip to content

Commit 9745031

Browse files
committed
Merge tag 'objtool-urgent-2026-03-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull objtool fixes from Ingo Molnar: - Fix cross-build bug by using HOSTCFLAGS for HAVE_XXHASH test - Fix klp bug by fixing detection of corrupt static branch/call entries - Handle unsupported pr_debug() usage more gracefully - Fix hypothetical klp bug by avoiding NULL pointer dereference when printing code symbol name - Fix data alignment bug in elf_add_data() causing mangled strings - Fix confusing ERROR_INSN() error message - Handle unexpected Clang RSP musical chairs causing false positive warnings - Fix another objtool stack overflow in validate_branch() * tag 'objtool-urgent-2026-03-15' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: objtool: Fix another stack overflow in validate_branch() objtool: Handle Clang RSP musical chairs objtool: Fix ERROR_INSN() error message objtool: Fix data alignment in elf_add_data() objtool: Use HOSTCFLAGS for HAVE_XXHASH test objtool/klp: Avoid NULL pointer dereference when printing code symbol name objtool/klp: Disable unsupported pr_debug() usage objtool/klp: Fix detection of corrupt static branch/call entries
2 parents be2e375 + 9a73f08 commit 9745031

6 files changed

Lines changed: 71 additions & 60 deletions

File tree

tools/objtool/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ endif
1313

1414
ifeq ($(ARCH_HAS_KLP),y)
1515
HAVE_XXHASH = $(shell printf "$(pound)include <xxhash.h>\nXXH3_state_t *state;int main() {}" | \
16-
$(HOSTCC) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
16+
$(HOSTCC) $(HOSTCFLAGS) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
1717
ifeq ($(HAVE_XXHASH),y)
1818
BUILD_KLP := y
1919
LIBXXHASH_CFLAGS := $(shell $(HOSTPKG_CONFIG) libxxhash --cflags 2>/dev/null) \

tools/objtool/arch/x86/decode.c

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -395,52 +395,36 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
395395
if (!rex_w)
396396
break;
397397

398-
if (modrm_reg == CFI_SP) {
399-
400-
if (mod_is_reg()) {
401-
/* mov %rsp, reg */
402-
ADD_OP(op) {
403-
op->src.type = OP_SRC_REG;
404-
op->src.reg = CFI_SP;
405-
op->dest.type = OP_DEST_REG;
406-
op->dest.reg = modrm_rm;
407-
}
408-
break;
409-
410-
} else {
411-
/* skip RIP relative displacement */
412-
if (is_RIP())
413-
break;
414-
415-
/* skip nontrivial SIB */
416-
if (have_SIB()) {
417-
modrm_rm = sib_base;
418-
if (sib_index != CFI_SP)
419-
break;
420-
}
421-
422-
/* mov %rsp, disp(%reg) */
423-
ADD_OP(op) {
424-
op->src.type = OP_SRC_REG;
425-
op->src.reg = CFI_SP;
426-
op->dest.type = OP_DEST_REG_INDIRECT;
427-
op->dest.reg = modrm_rm;
428-
op->dest.offset = ins.displacement.value;
429-
}
430-
break;
398+
if (mod_is_reg()) {
399+
/* mov reg, reg */
400+
ADD_OP(op) {
401+
op->src.type = OP_SRC_REG;
402+
op->src.reg = modrm_reg;
403+
op->dest.type = OP_DEST_REG;
404+
op->dest.reg = modrm_rm;
431405
}
432-
433406
break;
434407
}
435408

436-
if (rm_is_reg(CFI_SP)) {
409+
/* skip RIP relative displacement */
410+
if (is_RIP())
411+
break;
437412

438-
/* mov reg, %rsp */
413+
/* skip nontrivial SIB */
414+
if (have_SIB()) {
415+
modrm_rm = sib_base;
416+
if (sib_index != CFI_SP)
417+
break;
418+
}
419+
420+
/* mov %rsp, disp(%reg) */
421+
if (modrm_reg == CFI_SP) {
439422
ADD_OP(op) {
440423
op->src.type = OP_SRC_REG;
441-
op->src.reg = modrm_reg;
442-
op->dest.type = OP_DEST_REG;
443-
op->dest.reg = CFI_SP;
424+
op->src.reg = CFI_SP;
425+
op->dest.type = OP_DEST_REG_INDIRECT;
426+
op->dest.reg = modrm_rm;
427+
op->dest.offset = ins.displacement.value;
444428
}
445429
break;
446430
}

tools/objtool/check.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,6 +3000,20 @@ static int update_cfi_state(struct instruction *insn,
30003000
cfi->stack_size += 8;
30013001
}
30023002

3003+
else if (cfi->vals[op->src.reg].base == CFI_CFA) {
3004+
/*
3005+
* Clang RSP musical chairs:
3006+
*
3007+
* mov %rsp, %rdx [handled above]
3008+
* ...
3009+
* mov %rdx, %rbx [handled here]
3010+
* ...
3011+
* mov %rbx, %rsp [handled above]
3012+
*/
3013+
cfi->vals[op->dest.reg].base = CFI_CFA;
3014+
cfi->vals[op->dest.reg].offset = cfi->vals[op->src.reg].offset;
3015+
}
3016+
30033017

30043018
break;
30053019

@@ -3734,7 +3748,7 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
37343748
static int validate_branch(struct objtool_file *file, struct symbol *func,
37353749
struct instruction *insn, struct insn_state state);
37363750
static int do_validate_branch(struct objtool_file *file, struct symbol *func,
3737-
struct instruction *insn, struct insn_state state);
3751+
struct instruction *insn, struct insn_state *state);
37383752

37393753
static int validate_insn(struct objtool_file *file, struct symbol *func,
37403754
struct instruction *insn, struct insn_state *statep,
@@ -3999,7 +4013,7 @@ static int validate_insn(struct objtool_file *file, struct symbol *func,
39994013
* tools/objtool/Documentation/objtool.txt.
40004014
*/
40014015
static int do_validate_branch(struct objtool_file *file, struct symbol *func,
4002-
struct instruction *insn, struct insn_state state)
4016+
struct instruction *insn, struct insn_state *state)
40034017
{
40044018
struct instruction *next_insn, *prev_insn = NULL;
40054019
bool dead_end;
@@ -4030,7 +4044,7 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func,
40304044
return 1;
40314045
}
40324046

4033-
ret = validate_insn(file, func, insn, &state, prev_insn, next_insn,
4047+
ret = validate_insn(file, func, insn, state, prev_insn, next_insn,
40344048
&dead_end);
40354049

40364050
if (!insn->trace) {
@@ -4041,7 +4055,7 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func,
40414055
}
40424056

40434057
if (!dead_end && !next_insn) {
4044-
if (state.cfi.cfa.base == CFI_UNDEFINED)
4058+
if (state->cfi.cfa.base == CFI_UNDEFINED)
40454059
return 0;
40464060
if (file->ignore_unreachables)
40474061
return 0;
@@ -4066,7 +4080,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
40664080
int ret;
40674081

40684082
trace_depth_inc();
4069-
ret = do_validate_branch(file, func, insn, state);
4083+
ret = do_validate_branch(file, func, insn, &state);
40704084
trace_depth_dec();
40714085

40724086
return ret;

tools/objtool/elf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_
13751375
memcpy(sec->data->d_buf, data, size);
13761376

13771377
sec->data->d_size = size;
1378-
sec->data->d_align = 1;
1378+
sec->data->d_align = sec->sh.sh_addralign;
13791379

13801380
offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign);
13811381
sec->sh.sh_size = offset + size;

tools/objtool/include/objtool/warn.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static inline char *offstr(struct section *sec, unsigned long offset)
107107
#define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__)
108108
#define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__)
109109
#define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__)
110-
#define ERROR_INSN(insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)
110+
#define ERROR_INSN(insn, format, ...) ERROR_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)
111111

112112
extern bool debug;
113113
extern int indent;

tools/objtool/klp-diff.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,25 +1334,25 @@ static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
13341334
* be applied after static branch/call init, resulting in code corruption.
13351335
*
13361336
* Validate a special section entry to avoid that. Note that an inert
1337-
* tracepoint is harmless enough, in that case just skip the entry and print a
1338-
* warning. Otherwise, return an error.
1337+
* tracepoint or pr_debug() is harmless enough, in that case just skip the
1338+
* entry and print a warning. Otherwise, return an error.
13391339
*
1340-
* This is only a temporary limitation which will be fixed when livepatch adds
1341-
* support for submodules: fully self-contained modules which are embedded in
1342-
* the top-level livepatch module's data and which can be loaded on demand when
1343-
* their corresponding to-be-patched module gets loaded. Then klp relocs can
1344-
* be retired.
1340+
* TODO: This is only a temporary limitation which will be fixed when livepatch
1341+
* adds support for submodules: fully self-contained modules which are embedded
1342+
* in the top-level livepatch module's data and which can be loaded on demand
1343+
* when their corresponding to-be-patched module gets loaded. Then klp relocs
1344+
* can be retired.
13451345
*
13461346
* Return:
13471347
* -1: error: validation failed
1348-
* 1: warning: tracepoint skipped
1348+
* 1: warning: disabled tracepoint or pr_debug()
13491349
* 0: success
13501350
*/
13511351
static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym)
13521352
{
13531353
bool static_branch = !strcmp(sym->sec->name, "__jump_table");
13541354
bool static_call = !strcmp(sym->sec->name, ".static_call_sites");
1355-
struct symbol *code_sym = NULL;
1355+
const char *code_sym = NULL;
13561356
unsigned long code_offset = 0;
13571357
struct reloc *reloc;
13581358
int ret = 0;
@@ -1364,12 +1364,15 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym
13641364
const char *sym_modname;
13651365
struct export *export;
13661366

1367+
if (convert_reloc_sym(e->patched, reloc))
1368+
continue;
1369+
13671370
/* Static branch/call keys are always STT_OBJECT */
13681371
if (reloc->sym->type != STT_OBJECT) {
13691372

13701373
/* Save code location which can be printed below */
13711374
if (reloc->sym->type == STT_FUNC && !code_sym) {
1372-
code_sym = reloc->sym;
1375+
code_sym = reloc->sym->name;
13731376
code_offset = reloc_addend(reloc);
13741377
}
13751378

@@ -1392,16 +1395,26 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym
13921395
if (!strcmp(sym_modname, "vmlinux"))
13931396
continue;
13941397

1398+
if (!code_sym)
1399+
code_sym = "<unknown>";
1400+
13951401
if (static_branch) {
13961402
if (strstarts(reloc->sym->name, "__tracepoint_")) {
13971403
WARN("%s: disabling unsupported tracepoint %s",
1398-
code_sym->name, reloc->sym->name + 13);
1404+
code_sym, reloc->sym->name + 13);
1405+
ret = 1;
1406+
continue;
1407+
}
1408+
1409+
if (strstr(reloc->sym->name, "__UNIQUE_ID_ddebug_")) {
1410+
WARN("%s: disabling unsupported pr_debug()",
1411+
code_sym);
13991412
ret = 1;
14001413
continue;
14011414
}
14021415

14031416
ERROR("%s+0x%lx: unsupported static branch key %s. Use static_key_enabled() instead",
1404-
code_sym->name, code_offset, reloc->sym->name);
1417+
code_sym, code_offset, reloc->sym->name);
14051418
return -1;
14061419
}
14071420

@@ -1412,7 +1425,7 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym
14121425
}
14131426

14141427
ERROR("%s()+0x%lx: unsupported static call key %s. Use KLP_STATIC_CALL() instead",
1415-
code_sym->name, code_offset, reloc->sym->name);
1428+
code_sym, code_offset, reloc->sym->name);
14161429
return -1;
14171430
}
14181431

0 commit comments

Comments
 (0)