diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-09-13 17:29:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-09-15 02:25:12 -0400 |
commit | b9d989c7218ac922185d82ad46f3e58b27a4bea9 (patch) | |
tree | 91f4d00f2330f4c26debb445afbc386a8308e950 | |
parent | d4b80afbba49e968623330f1336da8c724da8aad (diff) |
x86/asm: Move the thread_info::status field to thread_struct
Because sched.h and thread_info.h are a tangled mess, I turned
in_compat_syscall() into a macro. If we had current_thread_struct()
or similar and we could use it from thread_info.h, then this would
be a bit cleaner.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jann Horn <jann@thejh.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/ccc8a1b2f41f9c264a41f771bb4a6539a642ad72.1473801993.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/entry/common.c | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/syscall.h | 20 | ||||
-rw-r--r-- | arch/x86/include/asm/thread_info.h | 23 | ||||
-rw-r--r-- | arch/x86/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/init.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 2 |
9 files changed, 27 insertions, 42 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 1433f6b4607d..871bbf975d4c 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c | |||
@@ -209,7 +209,7 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) | |||
209 | * special case only applies after poking regs and before the | 209 | * special case only applies after poking regs and before the |
210 | * very next return to user mode. | 210 | * very next return to user mode. |
211 | */ | 211 | */ |
212 | ti->status &= ~(TS_COMPAT|TS_I386_REGS_POKED); | 212 | current->thread.status &= ~(TS_COMPAT|TS_I386_REGS_POKED); |
213 | #endif | 213 | #endif |
214 | 214 | ||
215 | user_enter_irqoff(); | 215 | user_enter_irqoff(); |
@@ -307,7 +307,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) | |||
307 | unsigned int nr = (unsigned int)regs->orig_ax; | 307 | unsigned int nr = (unsigned int)regs->orig_ax; |
308 | 308 | ||
309 | #ifdef CONFIG_IA32_EMULATION | 309 | #ifdef CONFIG_IA32_EMULATION |
310 | ti->status |= TS_COMPAT; | 310 | current->thread.status |= TS_COMPAT; |
311 | #endif | 311 | #endif |
312 | 312 | ||
313 | if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) { | 313 | if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) { |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b22fb5a4ff3c..984a7bf17f6a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -389,6 +389,9 @@ struct thread_struct { | |||
389 | unsigned short fsindex; | 389 | unsigned short fsindex; |
390 | unsigned short gsindex; | 390 | unsigned short gsindex; |
391 | #endif | 391 | #endif |
392 | |||
393 | u32 status; /* thread synchronous flags */ | ||
394 | |||
392 | #ifdef CONFIG_X86_64 | 395 | #ifdef CONFIG_X86_64 |
393 | unsigned long fsbase; | 396 | unsigned long fsbase; |
394 | unsigned long gsbase; | 397 | unsigned long gsbase; |
@@ -435,6 +438,15 @@ struct thread_struct { | |||
435 | }; | 438 | }; |
436 | 439 | ||
437 | /* | 440 | /* |
441 | * Thread-synchronous status. | ||
442 | * | ||
443 | * This is different from the flags in that nobody else | ||
444 | * ever touches our thread-synchronous status, so we don't | ||
445 | * have to worry about atomic accesses. | ||
446 | */ | ||
447 | #define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ | ||
448 | |||
449 | /* | ||
438 | * Set IOPL bits in EFLAGS from given mask | 450 | * Set IOPL bits in EFLAGS from given mask |
439 | */ | 451 | */ |
440 | static inline void native_set_iopl_mask(unsigned mask) | 452 | static inline void native_set_iopl_mask(unsigned mask) |
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 4e23dd15c661..e3c95e8e61c5 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h | |||
@@ -60,7 +60,7 @@ static inline long syscall_get_error(struct task_struct *task, | |||
60 | * TS_COMPAT is set for 32-bit syscall entries and then | 60 | * TS_COMPAT is set for 32-bit syscall entries and then |
61 | * remains set until we return to user mode. | 61 | * remains set until we return to user mode. |
62 | */ | 62 | */ |
63 | if (task_thread_info(task)->status & (TS_COMPAT|TS_I386_REGS_POKED)) | 63 | if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED)) |
64 | /* | 64 | /* |
65 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | 65 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO |
66 | * and will match correctly in comparisons. | 66 | * and will match correctly in comparisons. |
@@ -116,7 +116,7 @@ static inline void syscall_get_arguments(struct task_struct *task, | |||
116 | unsigned long *args) | 116 | unsigned long *args) |
117 | { | 117 | { |
118 | # ifdef CONFIG_IA32_EMULATION | 118 | # ifdef CONFIG_IA32_EMULATION |
119 | if (task_thread_info(task)->status & TS_COMPAT) | 119 | if (task->thread.status & TS_COMPAT) |
120 | switch (i) { | 120 | switch (i) { |
121 | case 0: | 121 | case 0: |
122 | if (!n--) break; | 122 | if (!n--) break; |
@@ -177,7 +177,7 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
177 | const unsigned long *args) | 177 | const unsigned long *args) |
178 | { | 178 | { |
179 | # ifdef CONFIG_IA32_EMULATION | 179 | # ifdef CONFIG_IA32_EMULATION |
180 | if (task_thread_info(task)->status & TS_COMPAT) | 180 | if (task->thread.status & TS_COMPAT) |
181 | switch (i) { | 181 | switch (i) { |
182 | case 0: | 182 | case 0: |
183 | if (!n--) break; | 183 | if (!n--) break; |
@@ -234,18 +234,8 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
234 | 234 | ||
235 | static inline int syscall_get_arch(void) | 235 | static inline int syscall_get_arch(void) |
236 | { | 236 | { |
237 | #ifdef CONFIG_IA32_EMULATION | 237 | /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ |
238 | /* | 238 | return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; |
239 | * TS_COMPAT is set for 32-bit syscall entry and then | ||
240 | * remains set until we return to user mode. | ||
241 | * | ||
242 | * x32 tasks should be considered AUDIT_ARCH_X86_64. | ||
243 | */ | ||
244 | if (task_thread_info(current)->status & TS_COMPAT) | ||
245 | return AUDIT_ARCH_I386; | ||
246 | #endif | ||
247 | /* Both x32 and x86_64 are considered "64-bit". */ | ||
248 | return AUDIT_ARCH_X86_64; | ||
249 | } | 239 | } |
250 | #endif /* CONFIG_X86_32 */ | 240 | #endif /* CONFIG_X86_32 */ |
251 | 241 | ||
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 494c4b5ada34..c9dcfe7c7e4b 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
@@ -55,7 +55,6 @@ struct task_struct; | |||
55 | struct thread_info { | 55 | struct thread_info { |
56 | struct task_struct *task; /* main task structure */ | 56 | struct task_struct *task; /* main task structure */ |
57 | __u32 flags; /* low level flags */ | 57 | __u32 flags; /* low level flags */ |
58 | __u32 status; /* thread synchronous flags */ | ||
59 | __u32 cpu; /* current CPU */ | 58 | __u32 cpu; /* current CPU */ |
60 | }; | 59 | }; |
61 | 60 | ||
@@ -253,31 +252,17 @@ static inline int arch_within_stack_frames(const void * const stack, | |||
253 | 252 | ||
254 | #endif | 253 | #endif |
255 | 254 | ||
256 | /* | ||
257 | * Thread-synchronous status. | ||
258 | * | ||
259 | * This is different from the flags in that nobody else | ||
260 | * ever touches our thread-synchronous status, so we don't | ||
261 | * have to worry about atomic accesses. | ||
262 | */ | ||
263 | #define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ | ||
264 | #ifdef CONFIG_COMPAT | 255 | #ifdef CONFIG_COMPAT |
265 | #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ | 256 | #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ |
266 | #endif | 257 | #endif |
267 | |||
268 | #ifndef __ASSEMBLY__ | 258 | #ifndef __ASSEMBLY__ |
269 | 259 | ||
270 | static inline bool in_ia32_syscall(void) | ||
271 | { | ||
272 | #ifdef CONFIG_X86_32 | 260 | #ifdef CONFIG_X86_32 |
273 | return true; | 261 | #define in_ia32_syscall() true |
274 | #endif | 262 | #else |
275 | #ifdef CONFIG_IA32_EMULATION | 263 | #define in_ia32_syscall() (IS_ENABLED(CONFIG_IA32_EMULATION) && \ |
276 | if (current_thread_info()->status & TS_COMPAT) | 264 | current->thread.status & TS_COMPAT) |
277 | return true; | ||
278 | #endif | 265 | #endif |
279 | return false; | ||
280 | } | ||
281 | 266 | ||
282 | /* | 267 | /* |
283 | * Force syscall return via IRET by making it look as if there was | 268 | * Force syscall return via IRET by making it look as if there was |
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index db3a0af9b9ec..add5f90b93d4 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c | |||
@@ -36,7 +36,6 @@ void common(void) { | |||
36 | 36 | ||
37 | BLANK(); | 37 | BLANK(); |
38 | OFFSET(TI_flags, thread_info, flags); | 38 | OFFSET(TI_flags, thread_info, flags); |
39 | OFFSET(TI_status, thread_info, status); | ||
40 | 39 | ||
41 | BLANK(); | 40 | BLANK(); |
42 | OFFSET(TASK_addr_limit, task_struct, thread.addr_limit); | 41 | OFFSET(TASK_addr_limit, task_struct, thread.addr_limit); |
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 93982aebb398..2f2b8c7ccb85 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c | |||
@@ -317,7 +317,6 @@ static void __init fpu__init_system_ctx_switch(void) | |||
317 | on_boot_cpu = 0; | 317 | on_boot_cpu = 0; |
318 | 318 | ||
319 | WARN_ON_FPU(current->thread.fpu.fpstate_active); | 319 | WARN_ON_FPU(current->thread.fpu.fpstate_active); |
320 | current_thread_info()->status = 0; | ||
321 | 320 | ||
322 | if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) | 321 | if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) |
323 | eagerfpu = ENABLE; | 322 | eagerfpu = ENABLE; |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index b812cd0d7889..de9acaf2d371 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -510,7 +510,7 @@ void set_personality_ia32(bool x32) | |||
510 | current->personality &= ~READ_IMPLIES_EXEC; | 510 | current->personality &= ~READ_IMPLIES_EXEC; |
511 | /* in_compat_syscall() uses the presence of the x32 | 511 | /* in_compat_syscall() uses the presence of the x32 |
512 | syscall bit flag to determine compat status */ | 512 | syscall bit flag to determine compat status */ |
513 | current_thread_info()->status &= ~TS_COMPAT; | 513 | current->thread.status &= ~TS_COMPAT; |
514 | } else { | 514 | } else { |
515 | set_thread_flag(TIF_IA32); | 515 | set_thread_flag(TIF_IA32); |
516 | clear_thread_flag(TIF_X32); | 516 | clear_thread_flag(TIF_X32); |
@@ -518,7 +518,7 @@ void set_personality_ia32(bool x32) | |||
518 | current->mm->context.ia32_compat = TIF_IA32; | 518 | current->mm->context.ia32_compat = TIF_IA32; |
519 | current->personality |= force_personality32; | 519 | current->personality |= force_personality32; |
520 | /* Prepare the first "return" to user space */ | 520 | /* Prepare the first "return" to user space */ |
521 | current_thread_info()->status |= TS_COMPAT; | 521 | current->thread.status |= TS_COMPAT; |
522 | } | 522 | } |
523 | } | 523 | } |
524 | EXPORT_SYMBOL_GPL(set_personality_ia32); | 524 | EXPORT_SYMBOL_GPL(set_personality_ia32); |
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 5b88a1b26fc7..ce94c38cf4d6 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -934,7 +934,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value) | |||
934 | */ | 934 | */ |
935 | regs->orig_ax = value; | 935 | regs->orig_ax = value; |
936 | if (syscall_get_nr(child, regs) >= 0) | 936 | if (syscall_get_nr(child, regs) >= 0) |
937 | task_thread_info(child)->status |= TS_I386_REGS_POKED; | 937 | child->thread.status |= TS_I386_REGS_POKED; |
938 | break; | 938 | break; |
939 | 939 | ||
940 | case offsetof(struct user32, regs.eflags): | 940 | case offsetof(struct user32, regs.eflags): |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 04cb3212db2d..da20ecb5397a 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -783,7 +783,7 @@ static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) | |||
783 | * than the tracee. | 783 | * than the tracee. |
784 | */ | 784 | */ |
785 | #ifdef CONFIG_IA32_EMULATION | 785 | #ifdef CONFIG_IA32_EMULATION |
786 | if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED)) | 786 | if (current->thread.status & (TS_COMPAT|TS_I386_REGS_POKED)) |
787 | return __NR_ia32_restart_syscall; | 787 | return __NR_ia32_restart_syscall; |
788 | #endif | 788 | #endif |
789 | #ifdef CONFIG_X86_X32_ABI | 789 | #ifdef CONFIG_X86_X32_ABI |