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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 0 additions & 4 deletions
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

Lines changed: 4 additions & 3 deletions
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

Lines changed: 16 additions & 1 deletion
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

Lines changed: 2 additions & 15 deletions
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

Lines changed: 5 additions & 2 deletions
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

Lines changed: 4 additions & 5 deletions
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

Lines changed: 0 additions & 11 deletions
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

Lines changed: 3 additions & 3 deletions
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

0 commit comments

Comments
 (0)