s390/kasan: avoid false positives during stack unwind
Avoid kasan false positive when current task is interrupted in-between
stack frame allocation and backchain write instructions leaving new stack
frame backchain invalid. In particular if backchain is 0 the unwinder
tries to read pt_regs from the stack and might hit kasan poisoned bytes,
leading to kasan "stack-out-of-bounds" report.
Disable kasan instrumentation of unwinder stack reads, since this
limitation couldn't be handled otherwise with current backchain unwinder
implementation.
Fixes: 78c98f9074
("s390/unwind: introduce stack unwind API")
Reported-by: Julian Wiedmann <jwi@linux.ibm.com>
Tested-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
ac6639cd3d
commit
2095574632
|
@ -46,18 +46,18 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||
|
||||
regs = state->regs;
|
||||
if (unlikely(regs)) {
|
||||
sp = READ_ONCE_TASK_STACK(state->task, regs->gprs[15]);
|
||||
sp = READ_ONCE_NOCHECK(regs->gprs[15]);
|
||||
if (unlikely(outside_of_stack(state, sp))) {
|
||||
if (!update_stack_info(state, sp))
|
||||
goto out_err;
|
||||
}
|
||||
sf = (struct stack_frame *) sp;
|
||||
ip = READ_ONCE_TASK_STACK(state->task, sf->gprs[8]);
|
||||
ip = READ_ONCE_NOCHECK(sf->gprs[8]);
|
||||
reliable = false;
|
||||
regs = NULL;
|
||||
} else {
|
||||
sf = (struct stack_frame *) state->sp;
|
||||
sp = READ_ONCE_TASK_STACK(state->task, sf->back_chain);
|
||||
sp = READ_ONCE_NOCHECK(sf->back_chain);
|
||||
if (likely(sp)) {
|
||||
/* Non-zero back-chain points to the previous frame */
|
||||
if (unlikely(outside_of_stack(state, sp))) {
|
||||
|
@ -65,7 +65,7 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||
goto out_err;
|
||||
}
|
||||
sf = (struct stack_frame *) sp;
|
||||
ip = READ_ONCE_TASK_STACK(state->task, sf->gprs[8]);
|
||||
ip = READ_ONCE_NOCHECK(sf->gprs[8]);
|
||||
reliable = true;
|
||||
} else {
|
||||
/* No back-chain, look for a pt_regs structure */
|
||||
|
@ -73,9 +73,9 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||
if (!on_stack(info, sp, sizeof(struct pt_regs)))
|
||||
goto out_stop;
|
||||
regs = (struct pt_regs *) sp;
|
||||
if (user_mode(regs))
|
||||
if (READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE)
|
||||
goto out_stop;
|
||||
ip = READ_ONCE_TASK_STACK(state->task, regs->psw.addr);
|
||||
ip = READ_ONCE_NOCHECK(regs->psw.addr);
|
||||
reliable = true;
|
||||
}
|
||||
}
|
||||
|
@ -132,11 +132,11 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
|
|||
|
||||
/* Get the instruction pointer from pt_regs or the stack frame */
|
||||
if (regs) {
|
||||
ip = READ_ONCE_TASK_STACK(state->task, regs->psw.addr);
|
||||
ip = READ_ONCE_NOCHECK(regs->psw.addr);
|
||||
reliable = true;
|
||||
} else {
|
||||
sf = (struct stack_frame *) sp;
|
||||
ip = READ_ONCE_TASK_STACK(state->task, sf->gprs[8]);
|
||||
ip = READ_ONCE_NOCHECK(sf->gprs[8]);
|
||||
reliable = false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue