x86/arch_prctl/64: restore accidentally removed put_cpu in ARCH_SET_GS
Subsystems (2)
PATCH 1/1 x86/arch_prctl/64: restore accidentally removed put_cpu in ARCH_SET_GS
This fixes 731e33e39a5b95ad770 "Remove FSBASE/GSBASE < 4G optimization"
--- arch/x86/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kernel/process_64.c +1 -0
@@ -541,6 +541,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)load_gs_index (0 ); ret =wrmsrl_safe (MSR_KERNEL_GS_BASE , addr); } +put_cpu ();break ;case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry
Signature · 1 line
1.8.3.1
Quoted 1 line · Mateusz Guzik
This fixes
731e33e39a5b95ad770"Remove FSBASE/GSBASE < 4G optimization"
Indeed. How did that survive lockdep?
Quoted 21 lines
Signed-off-by Mateusz Guzik <[email protected]>--- arch/x86/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+)arch/x86/kernel/process_64.c +1
-1@@ -541,6 +541,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)load_gs_index (0 ); ret =wrmsrl_safe (MSR_KERNEL_GS_BASE , addr); } +put_cpu ();break ;case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry -- 1.8.3.1
Signature · 2 lines
Andy Lutomirski AMA Capital Management, LLC
Quoted 5 lines · Andy Lutomirski
Quoted 1 line · Mateusz Guzik
This fixes
731e33e39a5b95ad770"Remove FSBASE/GSBASE < 4G optimization"Indeed. How did that survive lockdep?
lockdep_sys_exit only checks actual locks.
In the common path after return from particular syscall interrupts get blindly disabled (as opposed to checking first that they are enabled). preemption count is not checked in the fast path at all and is checked elsewhere as a side effect of calls to e.g. schedule().
How about a hack along these lines (note I don't claim this is committable as it is, but it should work):
arch/x86/entry/common.c +19 -3
@@ -303,6 +303,24 @@ static void syscall_slow_exit_work(struct pt_regs *regs, u32 cached_flags)tracehook_report_syscall_exit (regs, step); } +#ifdef CONFIG_PROVE_LOCKING +/* +* Called after syscall handlers return. +*/ +__visible void syscall_assert_exit(struct pt_regs *regs) +{ +if (in_atomic () ||irqs_disabled ()) { +printk (KERN_ERR "invalid state on exit from syscall %ld: " +"in_atomic(): %d, irqs_disabled(): %d, pid: %d, " +"name: %s\n" , regs->orig_ax,in_atomic (), +irqs_disabled (), current->pid, current->comm); + } + +if (irqs_disabled ()) +local_irq_enable (); +} +#endif +/* * Called with IRQs on and fully valid regs. Returns with IRQs off in a * state such that we can immediately switch to user mode.
@@ -314,9 +332,7 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)CT_WARN_ON (ct_state () !=CONTEXT_KERNEL ); -if (IS_ENABLED (CONFIG_PROVE_LOCKING ) && -WARN (irqs_disabled (),"syscall %ld left IRQs disabled" , regs->orig_ax)) -local_irq_enable (); +syscall_assert_exit (regs);/* * First do one-time work. If these work items are enabled, we
arch/x86/entry/entry_64.S +7 -0
@@ -210,6 +210,12 @@ entry_SYSCALL_64_fastpath: movq %rax, RAX(%rsp) 1: +#ifdef CONFIG_PROVE_LOCKING + /* + * We want to validate bunch of stuff, which will clobber registers. + */ + jmp 2f +#endif /* * If we get here, then we know that pt_regs is clean for SYSRET64. * If we see that no exit work is required (which we are required
@@ -236,6 +242,7 @@ entry_SYSCALL_64_fastpath: */ TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) +2: SAVE_EXTRA_REGS movq %rsp, %rdi call syscall_return_slowpath /* returns with IRQs disabled */
Signature · 1 line
Mateusz Guzik
Quoted 76 lines · Mateusz Guzik
Quoted 5 lines · Andy Lutomirski
Quoted 1 line · Mateusz Guzik
This fixes
731e33e39a5b95ad770"Remove FSBASE/GSBASE < 4G optimization"Indeed. How did that survive lockdep?
lockdep_sys_exitonly checks actual locks.In the common path after return from particular syscall interrupts get blindly disabled (as opposed to checking first that they are enabled). preemption count is not checked in the fast path at all and is checked elsewhere as a side effect of calls to e.g.
schedule().How about a hack along these lines (note I don't claim this is committable as it is, but it should work):
arch/x86/entry/common.c +19
-3@@ -303,6 +303,24 @@ static void syscall_slow_exit_work(struct pt_regs *regs, u32 cached_flags)tracehook_report_syscall_exit (regs, step); } +#ifdef CONFIG_PROVE_LOCKING +/* +* Called after syscall handlers return. +*/ +__visible void syscall_assert_exit(struct pt_regs *regs) +{ +if (in_atomic () ||irqs_disabled ()) { +printk (KERN_ERR "invalid state on exit from syscall %ld: " +"in_atomic(): %d, irqs_disabled(): %d, pid: %d, " +"name: %s\n" , regs->orig_ax,in_atomic (), +irqs_disabled (), current->pid, current->comm); + } + +if (irqs_disabled ()) +local_irq_enable (); +} +#endif +/* * Called with IRQs on and fully valid regs. Returns with IRQs off in a * state such that we can immediately switch to user mode. @@ -314,9 +332,7 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)CT_WARN_ON (ct_state () !=CONTEXT_KERNEL ); -if (IS_ENABLED (CONFIG_PROVE_LOCKING ) && -WARN (irqs_disabled (),"syscall %ld left IRQs disabled" , regs->orig_ax)) -local_irq_enable (); +syscall_assert_exit (regs);/* * First do one-time work. If these work items are enabled, we arch/x86/entry/entry_64.S +6
-0@@ -210,6 +210,12 @@ entry_SYSCALL_64_fastpath: movq %rax, RAX(%rsp) 1: +#ifdef CONFIG_PROVE_LOCKING + /* + * We want to validate bunch of stuff, which will clobber registers. + */ + jmp 2f +#endif /* * If we get here, then we know that pt_regs is clean for SYSRET64. * If we see that no exit work is required (which we are required
arch/x86/entry/entry_64.S entry_SYSCALL_64_fastpath: · line 248
Quoted 7 lines
arch/x86/entry/entry_64.S +1
-0@@ -236,6 +242,7 @@ entry_SYSCALL_64_fastpath: */ TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) +2: SAVE_EXTRA_REGS movq %rsp, %rdi call syscall_return_slowpath /* returns with IRQs disabled */
It would be nice to do this in a cross-arch way. Maybe we could extend lockdep_sys_exit? Ingo, do you think that would be reasonable?
--Andy
Quoted 3 lines
--
Mateusz Guzik
Quoted 20 lines · Mateusz Guzik
This fixes
731e33e39a5b95ad770"Remove FSBASE/GSBASE < 4G optimization"Signed-off-by Mateusz Guzik <[email protected]>--- arch/x86/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+)arch/x86/kernel/process_64.c +1
-1@@ -541,6 +541,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)load_gs_index (0 ); ret =wrmsrl_safe (MSR_KERNEL_GS_BASE , addr); } +put_cpu ();break ;case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry --
Quoted 2 lines
1.8.3.1
Ingo, can you apply this before the merge window opens?
I just noticed that you weren't cc'd, so I'll repeat my ack:
And I'll ask, since IIRC you wrote it: would it make sense to augment lockdep_sys_exit to see if preemption got left disabled?
Thanks,
Andy
Quoted 17 lines · Andy Lutomirski
Quoted 16 lines · Mateusz Guzik
This fixes
731e33e39a5b95ad770"Remove FSBASE/GSBASE < 4G optimization"Signed-off-by Mateusz Guzik <[email protected]>--- arch/x86/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+)arch/x86/kernel/process_64.c +1
-0@@ -541,6 +541,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)load_gs_index (0 ); ret =wrmsrl_safe (MSR_KERNEL_GS_BASE , addr); } +put_cpu ();
Quoted 8 lines
Quoted 6 lines
arch/x86/kernel/process_64.c +0
-1break ;case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry -- 1.8.3.1
Ingo, can you apply this before the merge window opens?
Yeah, done, applied it to tip:x86/asm.
Quoted 6 lines
I just noticed that you weren't cc'd, so I'll repeat my ack:
Acked-by Andy Lutomirski <[email protected]>And I'll ask, since IIRC you wrote it: would it make sense to augment
lockdep_sys_exitto see if preemption got left disabled?
Yeah, absolutely. I'm quite sure early lockdep versions did such a check.
Thanks,
Ingo
tip-bot for Mateusz Guzik
merge bot[tip:x86/asm] x86/arch_prctl/64: Restore accidentally removed put_cpu() in ARCH_SET_GS
In reply to Mateusz Guzikx86/arch_prctl/64: Restore accidentally removed put_cpu() in ARCH_SET_GS
Commit-ID: 4afd0565552c87f23834db9121dd9cf6955d0b43 Gitweb: http://git.kernel.org/tip/4afd0565552c87f23834db9121dd9cf6955d0b43 Author: Mateusz Guzik <[email protected]> AuthorDate: Tue, 10 May 2016 22:56:43 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 13 May 2016 13:50:15 +0200
x86/arch_prctl/64: Restore accidentally removed put_cpu() in ARCH_SET_GS
This fixes an oversight in:
731e33e39a5b95 ("Remove FSBASE/GSBASE < 4G optimization")--- arch/x86/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kernel/process_64.c +1 -0
@@ -541,6 +541,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)load_gs_index (0 ); ret =wrmsrl_safe (MSR_KERNEL_GS_BASE , addr); } +put_cpu ();break ;case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry