Commit 9a73f085 authored by Josh Poimboeuf's avatar Josh Poimboeuf
Browse files

objtool: Fix another stack overflow in validate_branch()



The insn state is getting saved on the stack twice for each recursive
iteration.  No need for that, once is enough.

Fixes the following reported stack overflow:

  drivers/scsi/qla2xxx/qla_dbg.o: error: SIGSEGV: objtool stack overflow!
  Segmentation fault

Fixes: 70589843 ("objtool: Add option to trace function validation")
Reported-by: default avatarArnd Bergmann <arnd@arndb.de>
Closes: https://lore.kernel.org/90956545-2066-46e3-b547-10c884582eb0@app.fastmail.com
Link: https://patch.msgid.link/8b97f62d083457f3b0a29a424275f7957dd3372f.1772821683.git.jpoimboe@kernel.org


Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
parent 7fdaa640
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -3748,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,
@@ -4013,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;
@@ -4044,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) {
@@ -4055,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;
@@ -4080,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;