s390: fix preemption race in disable_sacf_uaccess
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 15 Dec 2017 13:16:04 +0000 (14:16 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 15 Dec 2017 14:05:21 +0000 (15:05 +0100)
With CONFIG_PREEMPT=y there is a possible race in disable_sacf_uaccess.

The new set_fs value needs to be stored the the task structure first,
the control register update needs to be second. Otherwise a preemptive
schedule may interrupt the code right after the control register update
has been done and the next time the task is scheduled we get an incorrect
value in the control register due to the old set_fs setting.

Fixes: 0aaba41b58 ("s390: remove all code using the access register mode")
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/lib/uaccess.c

index cae5a1e16cbd2d9ac5cc7b2fd1f67443919b8f80..c4f8039a35e8dda0bc20999b7db089e3ab09b613 100644 (file)
@@ -89,11 +89,11 @@ EXPORT_SYMBOL(enable_sacf_uaccess);
 
 void disable_sacf_uaccess(mm_segment_t old_fs)
 {
+       current->thread.mm_segment = old_fs;
        if (old_fs == USER_DS && test_facility(27)) {
                __ctl_load(S390_lowcore.user_asce, 1, 1);
                clear_cpu_flag(CIF_ASCE_PRIMARY);
        }
-       current->thread.mm_segment = old_fs;
 }
 EXPORT_SYMBOL(disable_sacf_uaccess);