Skip to content

Commit ed1cd6d

Browse files
chleroympe
authored andcommitted
powerpc: Activate CONFIG_THREAD_INFO_IN_TASK
This patch activates CONFIG_THREAD_INFO_IN_TASK which moves the thread_info into task_struct. Moving thread_info into task_struct has the following advantages: - It protects thread_info from corruption in the case of stack overflows. - Its address is harder to determine if stack addresses are leaked, making a number of attacks more difficult. This has the following consequences: - thread_info is now located at the beginning of task_struct. - The 'cpu' field is now in task_struct, and only exists when CONFIG_SMP is active. - thread_info doesn't have anymore the 'task' field. This patch: - Removes all recopy of thread_info struct when the stack changes. - Changes the CURRENT_THREAD_INFO() macro to point to current. - Selects CONFIG_THREAD_INFO_IN_TASK. - Modifies raw_smp_processor_id() to get ->cpu from current without including linux/sched.h to avoid circular inclusion and without including asm/asm-offsets.h to avoid symbol names duplication between ASM constants and C constants. - Modifies klp_init_thread_info() to take a task_struct pointer argument. Signed-off-by: Christophe Leroy <[email protected]> Reviewed-by: Nicholas Piggin <[email protected]> [mpe: Add task_stack.h to livepatch.h to fix build fails] Signed-off-by: Michael Ellerman <[email protected]>
1 parent 7aef376 commit ed1cd6d

21 files changed

+56
-194
lines changed

arch/powerpc/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ config PPC
238238
select RTC_LIB
239239
select SPARSE_IRQ
240240
select SYSCTL_EXCEPTION_TRACE
241+
select THREAD_INFO_IN_TASK
241242
select VIRT_TO_BUS if !PPC64
242243
#
243244
# Please keep this list sorted alphabetically.

arch/powerpc/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,13 @@ else
427427
endif
428428
endif
429429

430+
ifdef CONFIG_SMP
431+
prepare: task_cpu_prepare
432+
433+
task_cpu_prepare: prepare0
434+
$(eval KBUILD_CFLAGS += -D_TASK_CPU=$(shell awk '{if ($$2 == "TI_CPU") print $$3;}' include/generated/asm-offsets.h))
435+
endif
436+
430437
# Check toolchain versions:
431438
# - gcc-4.6 is the minimum kernel-wide version so nothing required.
432439
checkbin:

arch/powerpc/include/asm/irq.h

-4
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ struct pt_regs;
5151
extern struct thread_info *critirq_ctx[NR_CPUS];
5252
extern struct thread_info *dbgirq_ctx[NR_CPUS];
5353
extern struct thread_info *mcheckirq_ctx[NR_CPUS];
54-
extern void exc_lvl_ctx_init(void);
55-
#else
56-
#define exc_lvl_ctx_init()
5754
#endif
5855

5956
/*
@@ -62,7 +59,6 @@ extern void exc_lvl_ctx_init(void);
6259
extern struct thread_info *hardirq_ctx[NR_CPUS];
6360
extern struct thread_info *softirq_ctx[NR_CPUS];
6461

65-
extern void irq_ctx_init(void);
6662
void call_do_softirq(void *sp);
6763
void call_do_irq(struct pt_regs *regs, void *sp);
6864
extern void do_IRQ(struct pt_regs *regs);

arch/powerpc/include/asm/livepatch.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <linux/module.h>
2323
#include <linux/ftrace.h>
24+
#include <linux/sched/task_stack.h>
2425

2526
#ifdef CONFIG_LIVEPATCH
2627
static inline int klp_check_compiler_support(void)
@@ -43,13 +44,13 @@ static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
4344
return ftrace_location_range(faddr, faddr + 16);
4445
}
4546

46-
static inline void klp_init_thread_info(struct thread_info *ti)
47+
static inline void klp_init_thread_info(struct task_struct *p)
4748
{
4849
/* + 1 to account for STACK_END_MAGIC */
49-
ti->livepatch_sp = (unsigned long *)(ti + 1) + 1;
50+
task_thread_info(p)->livepatch_sp = end_of_stack(p) + 1;
5051
}
5152
#else
52-
static void klp_init_thread_info(struct thread_info *ti) { }
53+
static inline void klp_init_thread_info(struct task_struct *p) { }
5354
#endif /* CONFIG_LIVEPATCH */
5455

5556
#endif /* _ASM_POWERPC_LIVEPATCH_H */

arch/powerpc/include/asm/smp.h

+16-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,22 @@ int is_cpu_dead(unsigned int cpu);
8383
/* 32-bit */
8484
extern int smp_hw_index[];
8585

86-
#define raw_smp_processor_id() (current_thread_info()->cpu)
86+
/*
87+
* This is particularly ugly: it appears we can't actually get the definition
88+
* of task_struct here, but we need access to the CPU this task is running on.
89+
* Instead of using task_struct we're using _TASK_CPU which is extracted from
90+
* asm-offsets.h by kbuild to get the current processor ID.
91+
*
92+
* This also needs to be safeguarded when building asm-offsets.s because at
93+
* that time _TASK_CPU is not defined yet. It could have been guarded by
94+
* _TASK_CPU itself, but we want the build to fail if _TASK_CPU is missing
95+
* when building something else than asm-offsets.s
96+
*/
97+
#ifdef GENERATING_ASM_OFFSETS
98+
#define raw_smp_processor_id() (0)
99+
#else
100+
#define raw_smp_processor_id() (*(unsigned int *)((void *)current + _TASK_CPU))
101+
#endif
87102
#define hard_smp_processor_id() (smp_hw_index[smp_processor_id()])
88103

89104
static inline int get_hard_smp_processor_id(int cpu)

arch/powerpc/include/asm/thread_info.h

+2-15
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
#define THREAD_SIZE (1 << THREAD_SHIFT)
1919

2020
#ifdef CONFIG_PPC64
21-
#define CURRENT_THREAD_INFO(dest, sp) stringify_in_c(clrrdi dest, sp, THREAD_SHIFT)
21+
#define CURRENT_THREAD_INFO(dest, sp) stringify_in_c(ld dest, PACACURRENT(r13))
2222
#else
23-
#define CURRENT_THREAD_INFO(dest, sp) stringify_in_c(rlwinm dest, sp, 0, 0, 31-THREAD_SHIFT)
23+
#define CURRENT_THREAD_INFO(dest, sp) stringify_in_c(mr dest, r2)
2424
#endif
2525

2626
#ifndef __ASSEMBLY__
@@ -34,8 +34,6 @@
3434
* low level task data.
3535
*/
3636
struct thread_info {
37-
struct task_struct *task; /* main task structure */
38-
int cpu; /* cpu we're on */
3937
int preempt_count; /* 0 => preemptable,
4038
<0 => BUG */
4139
unsigned long local_flags; /* private flags for thread */
@@ -58,24 +56,13 @@ struct thread_info {
5856
*/
5957
#define INIT_THREAD_INFO(tsk) \
6058
{ \
61-
.task = &tsk, \
62-
.cpu = 0, \
6359
.preempt_count = INIT_PREEMPT_COUNT, \
6460
.flags = 0, \
6561
}
6662

6763
#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
6864

6965
/* how to get the thread information struct from C */
70-
static inline struct thread_info *current_thread_info(void)
71-
{
72-
unsigned long val;
73-
74-
asm (CURRENT_THREAD_INFO(%0,1) : "=r" (val));
75-
76-
return (struct thread_info *)val;
77-
}
78-
7966
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
8067

8168
#ifdef CONFIG_PPC_BOOK3S_64

arch/powerpc/kernel/asm-offsets.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* 2 of the License, or (at your option) any later version.
1414
*/
1515

16+
#define GENERATING_ASM_OFFSETS /* asm/smp.h */
17+
1618
#include <linux/compat.h>
1719
#include <linux/signal.h>
1820
#include <linux/sched.h>
@@ -97,6 +99,9 @@ int main(void)
9799
#endif
98100
#endif /* CONFIG_PPC64 */
99101
OFFSET(TASK_STACK, task_struct, stack);
102+
#ifdef CONFIG_SMP
103+
OFFSET(TI_CPU, task_struct, cpu);
104+
#endif
100105

101106
#ifdef CONFIG_LIVEPATCH
102107
OFFSET(TI_livepatch_sp, thread_info, livepatch_sp);
@@ -164,8 +169,6 @@ int main(void)
164169
OFFSET(TI_FLAGS, thread_info, flags);
165170
OFFSET(TI_LOCAL_FLAGS, thread_info, local_flags);
166171
OFFSET(TI_PREEMPT, thread_info, preempt_count);
167-
OFFSET(TI_TASK, thread_info, task);
168-
OFFSET(TI_CPU, thread_info, cpu);
169172

170173
#ifdef CONFIG_PPC64
171174
OFFSET(DCACHEL1BLOCKSIZE, ppc64_caches, l1d.block_size);

arch/powerpc/kernel/entry_32.S

+4-5
Original file line numberDiff line numberDiff line change
@@ -1165,10 +1165,6 @@ ret_from_debug_exc:
11651165
mfspr r9,SPRN_SPRG_THREAD
11661166
lwz r10,SAVED_KSP_LIMIT(r1)
11671167
stw r10,KSP_LIMIT(r9)
1168-
lwz r9,TASK_STACK-THREAD(r9)
1169-
CURRENT_THREAD_INFO(r10, r1)
1170-
lwz r10,TI_PREEMPT(r10)
1171-
stw r10,TI_PREEMPT(r9)
11721168
RESTORE_xSRR(SRR0,SRR1);
11731169
RESTORE_xSRR(CSRR0,CSRR1);
11741170
RESTORE_MMU_REGS;
@@ -1291,10 +1287,13 @@ BEGIN_FTR_SECTION
12911287
END_FTR_SECTION_IFSET(CPU_FTR_601)
12921288
lwz r3,_TRAP(r1)
12931289
andi. r0,r3,1
1294-
beq 4f
1290+
beq 5f
12951291
SAVE_NVGPRS(r1)
12961292
rlwinm r3,r3,0,0,30
12971293
stw r3,_TRAP(r1)
1294+
5: mfspr r2,SPRN_SPRG_THREAD
1295+
addi r2,r2,-THREAD
1296+
tovirt(r2,r2) /* set back r2 to current */
12981297
4: addi r3,r1,STACK_FRAME_OVERHEAD
12991298
bl unrecoverable_exception
13001299
/* shouldn't return */

arch/powerpc/kernel/exceptions-64e.S

-11
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,6 @@ special_reg_save:
7777
andi. r3,r3,MSR_PR
7878
bnelr
7979

80-
/* Copy info into temporary exception thread info */
81-
ld r11,PACAKSAVE(r13)
82-
CURRENT_THREAD_INFO(r11, r11)
83-
CURRENT_THREAD_INFO(r12, r1)
84-
ld r10,TI_FLAGS(r11)
85-
std r10,TI_FLAGS(r12)
86-
ld r10,TI_PREEMPT(r11)
87-
std r10,TI_PREEMPT(r12)
88-
ld r10,TI_TASK(r11)
89-
std r10,TI_TASK(r12)
90-
9180
/*
9281
* Advance to the next TLB exception frame for handler
9382
* types that don't do it automatically.

arch/powerpc/kernel/head_32.S

+3-3
Original file line numberDiff line numberDiff line change
@@ -834,9 +834,9 @@ __secondary_start:
834834
/* get current's stack and current */
835835
lis r1,secondary_ti@ha
836836
tophys(r1,r1)
837-
lwz r1,secondary_ti@l(r1)
838-
tophys(r2,r1)
839-
lwz r2,TI_TASK(r2)
837+
lwz r2,secondary_ti@l(r1)
838+
tophys(r1,r2)
839+
lwz r1,TASK_STACK(r1)
840840

841841
/* stack */
842842
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD

arch/powerpc/kernel/head_44x.S

+2-2
Original file line numberDiff line numberDiff line change
@@ -1021,8 +1021,8 @@ _GLOBAL(start_secondary_47x)
10211021

10221022
/* Get current's stack and current */
10231023
lis r1,secondary_ti@ha
1024-
lwz r1,secondary_ti@l(r1)
1025-
lwz r2,TI_TASK(r1)
1024+
lwz r2,secondary_ti@l(r1)
1025+
lwz r1,TASK_STACK(r2)
10261026

10271027
/* Current stack pointer */
10281028
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD

arch/powerpc/kernel/head_booke.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,7 @@ END_BTB_FLUSH_SECTION
155155
stw r10,GPR11(r11); \
156156
b 2f; \
157157
/* COMING FROM PRIV MODE */ \
158-
1: lwz r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r11); \
159-
lwz r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r11); \
160-
stw r9,TI_FLAGS-EXC_LVL_FRAME_OVERHEAD(r8); \
161-
stw r10,TI_PREEMPT-EXC_LVL_FRAME_OVERHEAD(r8); \
162-
lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \
163-
stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \
164-
mr r11,r8; \
158+
1: mr r11, r8; \
165159
2: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \
166160
stw r12,GPR12(r11); /* save various registers */\
167161
mflr r10; \

arch/powerpc/kernel/head_fsl_booke.S

+3-4
Original file line numberDiff line numberDiff line change
@@ -719,8 +719,7 @@ finish_tlb_load:
719719

720720
/* Get the next_tlbcam_idx percpu var */
721721
#ifdef CONFIG_SMP
722-
lwz r12, TASK_STACK-THREAD(r12)
723-
lwz r15, TI_CPU(r12)
722+
lwz r15, TI_CPU-THREAD(r12)
724723
lis r14, __per_cpu_offset@h
725724
ori r14, r14, __per_cpu_offset@l
726725
rlwinm r15, r15, 2, 0, 29
@@ -1093,8 +1092,8 @@ __secondary_start:
10931092

10941093
/* get current's stack and current */
10951094
lis r1,secondary_ti@ha
1096-
lwz r1,secondary_ti@l(r1)
1097-
lwz r2,TI_TASK(r1)
1095+
lwz r2,secondary_ti@l(r1)
1096+
lwz r1,TASK_STACK(r2)
10981097

10991098
/* stack */
11001099
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD

arch/powerpc/kernel/irq.c

+1-78
Original file line numberDiff line numberDiff line change
@@ -673,110 +673,33 @@ void do_IRQ(struct pt_regs *regs)
673673
set_irq_regs(old_regs);
674674
return;
675675
}
676-
677-
/* Prepare the thread_info in the irq stack */
678-
irqtp->task = curtp->task;
679-
irqtp->flags = 0;
680-
681-
/* Copy the preempt_count so that the [soft]irq checks work. */
682-
irqtp->preempt_count = curtp->preempt_count;
683-
684676
/* Switch stack and call */
685677
call_do_irq(regs, irqtp);
686678

687-
/* Restore stack limit */
688-
irqtp->task = NULL;
689-
690-
/* Copy back updates to the thread_info */
691-
if (irqtp->flags)
692-
set_bits(irqtp->flags, &curtp->flags);
693-
694679
set_irq_regs(old_regs);
695680
}
696681

697682
void __init init_IRQ(void)
698683
{
699684
if (ppc_md.init_IRQ)
700685
ppc_md.init_IRQ();
701-
702-
exc_lvl_ctx_init();
703-
704-
irq_ctx_init();
705686
}
706687

707688
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
708689
struct thread_info *critirq_ctx[NR_CPUS] __read_mostly;
709690
struct thread_info *dbgirq_ctx[NR_CPUS] __read_mostly;
710691
struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly;
711-
712-
void exc_lvl_ctx_init(void)
713-
{
714-
struct thread_info *tp;
715-
int i, cpu_nr;
716-
717-
for_each_possible_cpu(i) {
718-
#ifdef CONFIG_PPC64
719-
cpu_nr = i;
720-
#else
721-
#ifdef CONFIG_SMP
722-
cpu_nr = get_hard_smp_processor_id(i);
723-
#else
724-
cpu_nr = 0;
725-
#endif
726-
#endif
727-
728-
tp = critirq_ctx[cpu_nr];
729-
tp->cpu = cpu_nr;
730-
tp->preempt_count = 0;
731-
732-
#ifdef CONFIG_BOOKE
733-
tp = dbgirq_ctx[cpu_nr];
734-
tp->cpu = cpu_nr;
735-
tp->preempt_count = 0;
736-
737-
tp = mcheckirq_ctx[cpu_nr];
738-
tp->cpu = cpu_nr;
739-
tp->preempt_count = HARDIRQ_OFFSET;
740-
#endif
741-
}
742-
}
743692
#endif
744693

745694
struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
746695
struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
747696

748-
void irq_ctx_init(void)
749-
{
750-
struct thread_info *tp;
751-
int i;
752-
753-
for_each_possible_cpu(i) {
754-
tp = softirq_ctx[i];
755-
tp->cpu = i;
756-
klp_init_thread_info(tp);
757-
758-
tp = hardirq_ctx[i];
759-
tp->cpu = i;
760-
klp_init_thread_info(tp);
761-
}
762-
}
763-
764697
void do_softirq_own_stack(void)
765698
{
766-
struct thread_info *curtp, *irqtp;
699+
struct thread_info *irqtp;
767700

768-
curtp = current_thread_info();
769701
irqtp = softirq_ctx[smp_processor_id()];
770-
irqtp->task = curtp->task;
771-
irqtp->flags = 0;
772702
call_do_softirq(irqtp);
773-
irqtp->task = NULL;
774-
775-
/* Set any flag that may have been set on the
776-
* alternate stack
777-
*/
778-
if (irqtp->flags)
779-
set_bits(irqtp->flags, &curtp->flags);
780703
}
781704

782705
irq_hw_number_t virq_to_hw(unsigned int virq)

0 commit comments

Comments
 (0)