powerpc: split validate_sp into two functions
Most callers just want to validate an arbitrary kernel stack pointer, some need a particular size. Make the size case the exceptional one with an extra function. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20221127124942.1665522-15-npiggin@gmail.com
This commit is contained in:
parent
edbd0387f3
commit
4cefb0f6c5
|
@ -374,9 +374,18 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
|
|||
|
||||
#endif
|
||||
|
||||
/* Check that a certain kernel stack pointer is valid in task_struct p */
|
||||
int validate_sp(unsigned long sp, struct task_struct *p,
|
||||
unsigned long nbytes);
|
||||
/*
|
||||
* Check that a certain kernel stack pointer is a valid (minimum sized)
|
||||
* stack frame in task_struct p.
|
||||
*/
|
||||
int validate_sp(unsigned long sp, struct task_struct *p);
|
||||
|
||||
/*
|
||||
* validate the stack frame of a particular minimum size, used for when we are
|
||||
* looking at a certain object in the stack beyond the minimum.
|
||||
*/
|
||||
int validate_sp_size(unsigned long sp, struct task_struct *p,
|
||||
unsigned long nbytes);
|
||||
|
||||
/*
|
||||
* Prefetch macros.
|
||||
|
|
|
@ -2157,9 +2157,12 @@ static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int validate_sp(unsigned long sp, struct task_struct *p,
|
||||
unsigned long nbytes)
|
||||
/*
|
||||
* validate the stack frame of a particular minimum size, used for when we are
|
||||
* looking at a certain object in the stack beyond the minimum.
|
||||
*/
|
||||
int validate_sp_size(unsigned long sp, struct task_struct *p,
|
||||
unsigned long nbytes)
|
||||
{
|
||||
unsigned long stack_page = (unsigned long)task_stack_page(p);
|
||||
|
||||
|
@ -2175,7 +2178,10 @@ int validate_sp(unsigned long sp, struct task_struct *p,
|
|||
return valid_emergency_stack(sp, p, nbytes);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(validate_sp);
|
||||
int validate_sp(unsigned long sp, struct task_struct *p)
|
||||
{
|
||||
return validate_sp_size(sp, p, STACK_FRAME_OVERHEAD);
|
||||
}
|
||||
|
||||
static unsigned long ___get_wchan(struct task_struct *p)
|
||||
{
|
||||
|
@ -2183,13 +2189,12 @@ static unsigned long ___get_wchan(struct task_struct *p)
|
|||
int count = 0;
|
||||
|
||||
sp = p->thread.ksp;
|
||||
if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
|
||||
if (!validate_sp(sp, p))
|
||||
return 0;
|
||||
|
||||
do {
|
||||
sp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
|
||||
if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) ||
|
||||
task_is_running(p))
|
||||
if (!validate_sp(sp, p) || task_is_running(p))
|
||||
return 0;
|
||||
if (count > 0) {
|
||||
ip = READ_ONCE_NOCHECK(((unsigned long *)sp)[STACK_FRAME_LR_SAVE]);
|
||||
|
@ -2243,7 +2248,7 @@ void __no_sanitize_address show_stack(struct task_struct *tsk,
|
|||
lr = 0;
|
||||
printk("%sCall Trace:\n", loglvl);
|
||||
do {
|
||||
if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
|
||||
if (!validate_sp(sp, tsk))
|
||||
break;
|
||||
|
||||
stack = (unsigned long *) sp;
|
||||
|
@ -2270,7 +2275,7 @@ void __no_sanitize_address show_stack(struct task_struct *tsk,
|
|||
* could hold a pt_regs, if that does not fit then it can't
|
||||
* have regs.
|
||||
*/
|
||||
if (validate_sp(sp, tsk, STACK_SWITCH_FRAME_SIZE)
|
||||
if (validate_sp_size(sp, tsk, STACK_SWITCH_FRAME_SIZE)
|
||||
&& stack[STACK_INT_FRAME_MARKER_LONGS] == STACK_FRAME_REGS_MARKER) {
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
(sp + STACK_INT_FRAME_REGS);
|
||||
|
|
|
@ -43,7 +43,7 @@ void __no_sanitize_address arch_stack_walk(stack_trace_consume_fn consume_entry,
|
|||
unsigned long *stack = (unsigned long *) sp;
|
||||
unsigned long newsp, ip;
|
||||
|
||||
if (!validate_sp(sp, task, STACK_FRAME_OVERHEAD))
|
||||
if (!validate_sp(sp, task))
|
||||
return;
|
||||
|
||||
newsp = stack[0];
|
||||
|
|
|
@ -27,7 +27,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp)
|
|||
{
|
||||
if (sp & 0xf)
|
||||
return 0; /* must be 16-byte aligned */
|
||||
if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
|
||||
if (!validate_sp(sp, current))
|
||||
return 0;
|
||||
if (sp >= prev_sp + STACK_FRAME_MIN_SIZE)
|
||||
return 1;
|
||||
|
@ -53,7 +53,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
|
|||
sp = regs->gpr[1];
|
||||
perf_callchain_store(entry, perf_instruction_pointer(regs));
|
||||
|
||||
if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
|
||||
if (!validate_sp(sp, current))
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
|
@ -61,7 +61,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
|
|||
next_sp = fp[0];
|
||||
|
||||
if (next_sp == sp + STACK_INT_FRAME_SIZE &&
|
||||
validate_sp(sp, current, STACK_INT_FRAME_SIZE) &&
|
||||
validate_sp_size(sp, current, STACK_INT_FRAME_SIZE) &&
|
||||
fp[STACK_INT_FRAME_MARKER_LONGS] == STACK_FRAME_REGS_MARKER) {
|
||||
/*
|
||||
* This looks like an interrupt frame for an
|
||||
|
|
Loading…
Reference in New Issue