Skip to contentSkip to conversation

x86/arch_prctl/64: restore accidentally removed put_cpu in ARCH_SET_GS

PATCH In review Mateusz Guzik 5 participants 7 messages May 10, 2016 – May 13, 2016

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

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
index 4285f6a..6b16c36 100644
@@ -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
Acked-by on v1 1/1
#1 lore raw
Quoted 1 line · Mateusz Guzik

This fixes 731e33e39a5b95ad770 "Remove FSBASE/GSBASE < 4G optimization"

Indeed. How did that survive lockdep?

Quoted 21 lines
---
 arch/x86/kernel/process_64.c | 1 +
 1 file changed, 1 insertion(+)
arch/x86/kernel/process_64.c +1 -1
index 4285f6a..6b16c36 100644
@@ -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
#2 lore raw
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
index ec138e5..5887bc7 100644
@@ -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
index 9ee0da1..6c5cc23 100644
@@ -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
#3 lore raw
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_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
index ec138e5..5887bc7 100644
@@ -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
index 9ee0da1..6c5cc23 100644
@@ -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

maintainer Acked-by on v1 1/1
#4 lore raw
In reply to Mateusz Guzik
Quoted 20 lines · Mateusz Guzik

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 -1
index 4285f6a..6b16c36 100644
@@ -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

#5 lore raw
Quoted 17 lines · Andy Lutomirski
Quoted 16 lines · Mateusz Guzik

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
index 4285f6a..6b16c36 100644
@@ -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 -1
                break;
        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:

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?

Yeah, absolutely. I'm quite sure early lockdep versions did such a check.

Thanks,

Ingo

#6 lore raw

[tip:x86/asm] x86/arch_prctl/64: Restore accidentally removed put_cpu() in ARCH_SET_GS

In reply to Mateusz Guzik
x86/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")
Cc Alexander Shishkin <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Vince Weaver <[email protected]>
---
 arch/x86/kernel/process_64.c | 1 +
 1 file changed, 1 insertion(+)
arch/x86/kernel/process_64.c +1 -0
index 4285f6a..6b16c36 100644
@@ -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