Skip to content

Commit e504e74

Browse files
jpoimboesuryasaimadhu
authored andcommitted
x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
KASAN reserves "redzone" areas between stack frames in order to detect stack overruns. A read or write to such an area triggers a KASAN "stack-out-of-bounds" BUG. Normally, the ORC unwinder stays in-bounds and doesn't access the redzone. But sometimes it can't find ORC metadata for a given instruction. This can happen for code which is missing ORC metadata, or for generated code. In such cases, the unwinder attempts to fall back to frame pointers, as a best-effort type thing. This fallback often works, but when it doesn't, the unwinder can get confused and go off into the weeds into the KASAN redzone, triggering the aforementioned KASAN BUG. But in this case, the unwinder's confusion is actually harmless and working as designed. It already has checks in place to prevent off-stack accesses, but those checks get short-circuited by the KASAN BUG. And a BUG is a lot more disruptive than a harmless unwinder warning. Disable the KASAN checks by using READ_ONCE_NOCHECK() for all stack accesses. This finishes the job started by commit 881125b ("x86/unwind: Disable KASAN checking in the ORC unwinder"), which only partially fixed the issue. Fixes: ee9f8fc ("x86/unwind: Add the ORC unwinder") Reported-by: Ivan Babrou <ivan@cloudflare.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Tested-by: Ivan Babrou <ivan@cloudflare.com> Cc: stable@kernel.org Link: https://lkml.kernel.org/r/9583327904ebbbeda399eca9c56d6c7085ac20fe.1612534649.git.jpoimboe@redhat.com
1 parent a38fd87 commit e504e74

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

arch/x86/kernel/unwind_orc.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,8 @@ static bool deref_stack_regs(struct unwind_state *state, unsigned long addr,
367367
if (!stack_access_ok(state, addr, sizeof(struct pt_regs)))
368368
return false;
369369

370-
*ip = regs->ip;
371-
*sp = regs->sp;
370+
*ip = READ_ONCE_NOCHECK(regs->ip);
371+
*sp = READ_ONCE_NOCHECK(regs->sp);
372372
return true;
373373
}
374374

@@ -380,8 +380,8 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr
380380
if (!stack_access_ok(state, addr, IRET_FRAME_SIZE))
381381
return false;
382382

383-
*ip = regs->ip;
384-
*sp = regs->sp;
383+
*ip = READ_ONCE_NOCHECK(regs->ip);
384+
*sp = READ_ONCE_NOCHECK(regs->sp);
385385
return true;
386386
}
387387

@@ -402,12 +402,12 @@ static bool get_reg(struct unwind_state *state, unsigned int reg_off,
402402
return false;
403403

404404
if (state->full_regs) {
405-
*val = ((unsigned long *)state->regs)[reg];
405+
*val = READ_ONCE_NOCHECK(((unsigned long *)state->regs)[reg]);
406406
return true;
407407
}
408408

409409
if (state->prev_regs) {
410-
*val = ((unsigned long *)state->prev_regs)[reg];
410+
*val = READ_ONCE_NOCHECK(((unsigned long *)state->prev_regs)[reg]);
411411
return true;
412412
}
413413

0 commit comments

Comments
 (0)