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;

