Make sure the kernel_uaccess_faults_ok is updated before a
pagefault can hit and the last loads/stores issued before
resotring kernel_uaccess_faults_ok.

Signed-off-by: Masami Hiramatsu <[email protected]>
---
 fs/namespace.c |    2 ++
 mm/maccess.c   |   12 ++++++------
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index a677b59efd74..88a8e0eb6234 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2699,6 +2699,7 @@ static long exact_copy_from_user(void *to, const void 
__user * from,
                return n;
 
        current->kernel_uaccess_faults_ok++;
+       barrier();
        while (n) {
                if (__get_user(c, f)) {
                        memset(t, 0, n);
@@ -2708,6 +2709,7 @@ static long exact_copy_from_user(void *to, const void 
__user * from,
                f++;
                n--;
        }
+       barrier();
        current->kernel_uaccess_faults_ok--;
        return n;
 }
diff --git a/mm/maccess.c b/mm/maccess.c
index f3416632e5a4..7a9752d59587 100644
--- a/mm/maccess.c
+++ b/mm/maccess.c
@@ -29,12 +29,12 @@ long __probe_kernel_read(void *dst, const void *src, size_t 
size)
        mm_segment_t old_fs = get_fs();
 
        set_fs(KERNEL_DS);
-       pagefault_disable();
        current->kernel_uaccess_faults_ok++;
+       pagefault_disable();
        ret = __copy_from_user_inatomic(dst,
                        (__force const void __user *)src, size);
-       current->kernel_uaccess_faults_ok--;
        pagefault_enable();
+       current->kernel_uaccess_faults_ok--;
        set_fs(old_fs);
 
        return ret ? -EFAULT : 0;
@@ -59,11 +59,11 @@ long __probe_kernel_write(void *dst, const void *src, 
size_t size)
        mm_segment_t old_fs = get_fs();
 
        set_fs(KERNEL_DS);
-       pagefault_disable();
        current->kernel_uaccess_faults_ok++;
+       pagefault_disable();
        ret = __copy_to_user_inatomic((__force void __user *)dst, src, size);
-       current->kernel_uaccess_faults_ok--;
        pagefault_enable();
+       current->kernel_uaccess_faults_ok--;
        set_fs(old_fs);
 
        return ret ? -EFAULT : 0;
@@ -97,16 +97,16 @@ long strncpy_from_unsafe(char *dst, const void 
*unsafe_addr, long count)
                return 0;
 
        set_fs(KERNEL_DS);
-       pagefault_disable();
        current->kernel_uaccess_faults_ok++;
+       pagefault_disable();
 
        do {
                ret = __get_user(*dst++, (const char __user __force *)src++);
        } while (dst[-1] && ret == 0 && src - unsafe_addr < count);
 
-       current->kernel_uaccess_faults_ok--;
        dst[-1] = '\0';
        pagefault_enable();
+       current->kernel_uaccess_faults_ok--;
        set_fs(old_fs);
 
        return ret ? -EFAULT : src - unsafe_addr;

Reply via email to