Patch "powerpc/uaccess: Avoid might_fault() when user access is enabled" has been added to the 5.11-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    powerpc/uaccess: Avoid might_fault() when user access is enabled

to the 5.11-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     powerpc-uaccess-avoid-might_fault-when-user-access-i.patch
and it can be found in the queue-5.11 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 7ecba7cf3e1735508c1ea5ea5846488ec868c11b
Author: Alexey Kardashevskiy <aik@xxxxxxxxx>
Date:   Mon Feb 8 16:57:40 2021 +1100

    powerpc/uaccess: Avoid might_fault() when user access is enabled
    
    [ Upstream commit 7d506ca97b665b95e698a53697dad99fae813c1a ]
    
    The amount of code executed with enabled user space access (unlocked
    KUAP) should be minimal. However with CONFIG_PROVE_LOCKING or
    CONFIG_DEBUG_ATOMIC_SLEEP enabled, might_fault() calls into various
    parts of the kernel, and may even end up replaying interrupts which in
    turn may access user space and forget to restore the KUAP state.
    
    The problem places are:
      1. strncpy_from_user (and similar) which unlock KUAP and call
         unsafe_get_user -> __get_user_allowed -> __get_user_nocheck()
         with do_allow=false to skip KUAP as the caller took care of it.
      2. __unsafe_put_user_goto() which is called with unlocked KUAP.
    
    eg:
      WARNING: CPU: 30 PID: 1 at arch/powerpc/include/asm/book3s/64/kup.h:324 arch_local_irq_restore+0x160/0x190
      NIP arch_local_irq_restore+0x160/0x190
      LR  lock_is_held_type+0x140/0x200
      Call Trace:
        0xc00000007f392ff8 (unreliable)
        ___might_sleep+0x180/0x320
        __might_fault+0x50/0xe0
        filldir64+0x2d0/0x5d0
        call_filldir+0xc8/0x180
        ext4_readdir+0x948/0xb40
        iterate_dir+0x1ec/0x240
        sys_getdents64+0x80/0x290
        system_call_exception+0x160/0x280
        system_call_common+0xf0/0x27c
    
    Change __get_user_nocheck() to look at `do_allow` to decide whether to
    skip might_fault(). Since strncpy_from_user/etc call might_fault()
    anyway before unlocking KUAP, there should be no visible change.
    
    Drop might_fault() in __unsafe_put_user_goto() as it is only called
    from unsafe_put_user(), which already has KUAP unlocked.
    
    Since keeping might_fault() is still desirable for debugging, add
    calls to it in user_[read|write]_access_begin(). That also allows us
    to drop the is_kernel_addr() test, because there should be no code
    using user_[read|write]_access_begin() in order to access a kernel
    address.
    
    Fixes: de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace Access Protection")
    Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxxxx>
    [mpe: Combine with related patch from myself, merge change logs]
    Signed-off-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20210204121612.32721-1-aik@xxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index 501c9a79038c0..f53bfefb4a577 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -216,8 +216,6 @@ do {								\
 #define __put_user_nocheck_goto(x, ptr, size, label)		\
 do {								\
 	__typeof__(*(ptr)) __user *__pu_addr = (ptr);		\
-	if (!is_kernel_addr((unsigned long)__pu_addr))		\
-		might_fault();					\
 	__chk_user_ptr(ptr);					\
 	__put_user_size_goto((x), __pu_addr, (size), label);	\
 } while (0)
@@ -313,7 +311,7 @@ do {								\
 	__typeof__(size) __gu_size = (size);			\
 								\
 	__chk_user_ptr(__gu_addr);				\
-	if (!is_kernel_addr((unsigned long)__gu_addr))		\
+	if (do_allow && !is_kernel_addr((unsigned long)__gu_addr)) \
 		might_fault();					\
 	barrier_nospec();					\
 	if (do_allow)								\
@@ -508,6 +506,9 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
 {
 	if (unlikely(!access_ok(ptr, len)))
 		return false;
+
+	might_fault();
+
 	allow_read_write_user((void __user *)ptr, ptr, len);
 	return true;
 }
@@ -521,6 +522,9 @@ user_read_access_begin(const void __user *ptr, size_t len)
 {
 	if (unlikely(!access_ok(ptr, len)))
 		return false;
+
+	might_fault();
+
 	allow_read_from_user(ptr, len);
 	return true;
 }
@@ -532,6 +536,9 @@ user_write_access_begin(const void __user *ptr, size_t len)
 {
 	if (unlikely(!access_ok(ptr, len)))
 		return false;
+
+	might_fault();
+
 	allow_write_to_user((void __user *)ptr, len);
 	return true;
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux