Skip to content

Commit cbc9565

Browse files
committed
powerpc: Remove ksp_limit on ppc64
We've been keeping that field in thread_struct for a while, it contains the "limit" of the current stack pointer and is meant to be used for detecting stack overflows. It has a few problems however: - First, it was never actually *used* on 64-bit. Set and updated but not actually exploited - When switching stack to/from irq and softirq stacks, it's update is racy unless we hard disable interrupts, which is costly. This is fine on 32-bit as we don't soft-disable there but not on 64-bit. Thus rather than fixing 2 in order to implement 1 in some hypothetical future, let's remove the code completely from 64-bit. In order to avoid a clutter of ifdef's, we remove the updates from C code completely during interrupt stack switching, and instead maintain it from the asm helper that is used to do the stack switching in the first place. Signed-off-by: Benjamin Herrenschmidt <[email protected]>
1 parent 0366a1c commit cbc9565

File tree

6 files changed

+23
-18
lines changed

6 files changed

+23
-18
lines changed

arch/powerpc/include/asm/processor.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ typedef struct {
149149

150150
struct thread_struct {
151151
unsigned long ksp; /* Kernel stack pointer */
152-
unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
153-
154152
#ifdef CONFIG_PPC64
155153
unsigned long ksp_vsid;
156154
#endif
@@ -162,6 +160,7 @@ struct thread_struct {
162160
#endif
163161
#ifdef CONFIG_PPC32
164162
void *pgdir; /* root of page-table tree */
163+
unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
165164
#endif
166165
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
167166
/*
@@ -321,7 +320,6 @@ struct thread_struct {
321320
#else
322321
#define INIT_THREAD { \
323322
.ksp = INIT_SP, \
324-
.ksp_limit = INIT_SP_LIMIT, \
325323
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
326324
.fs = KERNEL_DS, \
327325
.fpr = {{0}}, \

arch/powerpc/kernel/asm-offsets.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ int main(void)
8080
DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr));
8181
#else
8282
DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
83+
DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16));
84+
DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
8385
#endif /* CONFIG_PPC64 */
8486

8587
DEFINE(KSP, offsetof(struct thread_struct, ksp));
86-
DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
8788
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
8889
#ifdef CONFIG_BOOKE
8990
DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0]));

arch/powerpc/kernel/irq.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,6 @@ void do_IRQ(struct pt_regs *regs)
496496
{
497497
struct pt_regs *old_regs = set_irq_regs(regs);
498498
struct thread_info *curtp, *irqtp;
499-
unsigned long saved_sp_limit;
500499

501500
/* Switch to the irq stack to handle this */
502501
curtp = current_thread_info();
@@ -509,12 +508,6 @@ void do_IRQ(struct pt_regs *regs)
509508
return;
510509
}
511510

512-
/* Adjust the stack limit */
513-
saved_sp_limit = current->thread.ksp_limit;
514-
current->thread.ksp_limit = (unsigned long)irqtp +
515-
_ALIGN_UP(sizeof(struct thread_info), 16);
516-
517-
518511
/* Prepare the thread_info in the irq stack */
519512
irqtp->task = curtp->task;
520513
irqtp->flags = 0;
@@ -526,7 +519,6 @@ void do_IRQ(struct pt_regs *regs)
526519
call_do_irq(regs, irqtp);
527520

528521
/* Restore stack limit */
529-
current->thread.ksp_limit = saved_sp_limit;
530522
irqtp->task = NULL;
531523

532524
/* Copy back updates to the thread_info */
@@ -604,16 +596,12 @@ void irq_ctx_init(void)
604596
static inline void do_softirq_onstack(void)
605597
{
606598
struct thread_info *curtp, *irqtp;
607-
unsigned long saved_sp_limit = current->thread.ksp_limit;
608599

609600
curtp = current_thread_info();
610601
irqtp = softirq_ctx[smp_processor_id()];
611602
irqtp->task = curtp->task;
612603
irqtp->flags = 0;
613-
current->thread.ksp_limit = (unsigned long)irqtp +
614-
_ALIGN_UP(sizeof(struct thread_info), 16);
615604
call_do_softirq(irqtp);
616-
current->thread.ksp_limit = saved_sp_limit;
617605
irqtp->task = NULL;
618606

619607
/* Set any flag that may have been set on the

arch/powerpc/kernel/misc_32.S

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,41 @@
3636

3737
.text
3838

39+
/*
40+
* We store the saved ksp_limit in the unused part
41+
* of the STACK_FRAME_OVERHEAD
42+
*/
3943
_GLOBAL(call_do_softirq)
4044
mflr r0
4145
stw r0,4(r1)
46+
lwz r10,THREAD+KSP_LIMIT(r2)
47+
addi r11,r3,THREAD_INFO_GAP
4248
stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
4349
mr r1,r3
50+
stw r10,8(r1)
51+
stw r11,THREAD+KSP_LIMIT(r2)
4452
bl __do_softirq
53+
lwz r10,8(r1)
4554
lwz r1,0(r1)
4655
lwz r0,4(r1)
56+
stw r10,THREAD+KSP_LIMIT(r2)
4757
mtlr r0
4858
blr
4959

5060
_GLOBAL(call_do_irq)
5161
mflr r0
5262
stw r0,4(r1)
63+
lwz r10,THREAD+KSP_LIMIT(r2)
64+
addi r11,r3,THREAD_INFO_GAP
5365
stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
5466
mr r1,r4
67+
stw r10,8(r1)
68+
stw r11,THREAD+KSP_LIMIT(r2)
5569
bl __do_irq
70+
lwz r10,8(r1)
5671
lwz r1,0(r1)
5772
lwz r0,4(r1)
73+
stw r10,THREAD+KSP_LIMIT(r2)
5874
mtlr r0
5975
blr
6076

arch/powerpc/kernel/process.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,9 +1000,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
10001000
kregs = (struct pt_regs *) sp;
10011001
sp -= STACK_FRAME_OVERHEAD;
10021002
p->thread.ksp = sp;
1003+
#ifdef CONFIG_PPC32
10031004
p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
10041005
_ALIGN_UP(sizeof(struct thread_info), 16);
1005-
1006+
#endif
10061007
#ifdef CONFIG_HAVE_HW_BREAKPOINT
10071008
p->thread.ptrace_bps[0] = NULL;
10081009
#endif

arch/powerpc/lib/sstep.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
15051505
*/
15061506
if ((ra == 1) && !(regs->msr & MSR_PR) \
15071507
&& (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
1508+
#ifdef CONFIG_PPC32
15081509
/*
15091510
* Check if we will touch kernel sack overflow
15101511
*/
@@ -1513,7 +1514,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
15131514
err = -EINVAL;
15141515
break;
15151516
}
1516-
1517+
#endif /* CONFIG_PPC32 */
15171518
/*
15181519
* Check if we already set since that means we'll
15191520
* lose the previous value.

0 commit comments

Comments
 (0)