Commit 97450311 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents be2e3750 9a73f085
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@ endif

ifeq ($(ARCH_HAS_KLP),y)
	HAVE_XXHASH = $(shell printf "$(pound)include <xxhash.h>\nXXH3_state_t *state;int main() {}" | \
		      $(HOSTCC) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
		      $(HOSTCC) $(HOSTCFLAGS) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
	ifeq ($(HAVE_XXHASH),y)
		BUILD_KLP	 := y
		LIBXXHASH_CFLAGS := $(shell $(HOSTPKG_CONFIG) libxxhash --cflags 2>/dev/null) \
+23 −39
Original line number Diff line number Diff line
@@ -395,19 +395,17 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
		if (!rex_w)
			break;

		if (modrm_reg == CFI_SP) {

		if (mod_is_reg()) {
				/* mov %rsp, reg */
			/* mov reg, reg */
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
					op->src.reg = CFI_SP;
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = modrm_rm;
			}
			break;
		}

			} else {
		/* skip RIP relative displacement */
		if (is_RIP())
			break;
@@ -420,6 +418,7 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
		}

		/* mov %rsp, disp(%reg) */
		if (modrm_reg == CFI_SP) {
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = CFI_SP;
@@ -430,21 +429,6 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
			break;
		}

			break;
		}

		if (rm_is_reg(CFI_SP)) {

			/* mov reg, %rsp */
			ADD_OP(op) {
				op->src.type = OP_SRC_REG;
				op->src.reg = modrm_reg;
				op->dest.type = OP_DEST_REG;
				op->dest.reg = CFI_SP;
			}
			break;
		}

		fallthrough;
	case 0x88:
		if (!rex_w)
+19 −5
Original line number Diff line number Diff line
@@ -3000,6 +3000,20 @@ static int update_cfi_state(struct instruction *insn,
				cfi->stack_size += 8;
			}

			else if (cfi->vals[op->src.reg].base == CFI_CFA) {
				/*
				 * Clang RSP musical chairs:
				 *
				 *   mov %rsp, %rdx [handled above]
				 *   ...
				 *   mov %rdx, %rbx [handled here]
				 *   ...
				 *   mov %rbx, %rsp [handled above]
				 */
				cfi->vals[op->dest.reg].base = CFI_CFA;
				cfi->vals[op->dest.reg].offset = cfi->vals[op->src.reg].offset;
			}


			break;

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

static int validate_insn(struct objtool_file *file, struct symbol *func,
			 struct instruction *insn, struct insn_state *statep,
@@ -3999,7 +4013,7 @@ static int validate_insn(struct objtool_file *file, struct symbol *func,
 * tools/objtool/Documentation/objtool.txt.
 */
static int do_validate_branch(struct objtool_file *file, struct symbol *func,
			      struct instruction *insn, struct insn_state state)
			      struct instruction *insn, struct insn_state *state)
{
	struct instruction *next_insn, *prev_insn = NULL;
	bool dead_end;
@@ -4030,7 +4044,7 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func,
			return 1;
		}

		ret = validate_insn(file, func, insn, &state, prev_insn, next_insn,
		ret = validate_insn(file, func, insn, state, prev_insn, next_insn,
				    &dead_end);

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

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

	trace_depth_inc();
	ret = do_validate_branch(file, func, insn, state);
	ret = do_validate_branch(file, func, insn, &state);
	trace_depth_dec();

	return ret;
+1 −1
Original line number Diff line number Diff line
@@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_
		memcpy(sec->data->d_buf, data, size);

	sec->data->d_size = size;
	sec->data->d_align = 1;
	sec->data->d_align = sec->sh.sh_addralign;

	offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign);
	sec->sh.sh_size = offset + size;
+1 −1
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ static inline char *offstr(struct section *sec, unsigned long offset)
#define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__)
#define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__)
#define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__)
#define ERROR_INSN(insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)
#define ERROR_INSN(insn, format, ...) ERROR_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)

extern bool debug;
extern int indent;
Loading