Patch "powerpc/kuap: Restore AMR after replaying soft interrupts" 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/kuap: Restore AMR after replaying soft interrupts

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-kuap-restore-amr-after-replaying-soft-interr.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 311b2f0a833387b0302c98cd600f79de8c935ed1
Author: Alexey Kardashevskiy <aik@xxxxxxxxx>
Date:   Tue Feb 2 20:15:41 2021 +1100

    powerpc/kuap: Restore AMR after replaying soft interrupts
    
    [ Upstream commit 60a707d0c99aff4eadb7fd334c5fd21df386723e ]
    
    Since de78a9c42a79 ("powerpc: Add a framework for Kernel Userspace
    Access Protection"), user access helpers call user_{read|write}_access_{begin|end}
    when user space access is allowed.
    
    Commit 890274c2dc4c ("powerpc/64s: Implement KUAP for Radix MMU") made
    the mentioned helpers program a AMR special register to allow such
    access for a short period of time, most of the time AMR is expected to
    block user memory access by the kernel.
    
    Since the code accesses the user space memory, unsafe_get_user() calls
    might_fault() which calls arch_local_irq_restore() if either
    CONFIG_PROVE_LOCKING or CONFIG_DEBUG_ATOMIC_SLEEP is enabled.
    arch_local_irq_restore() then attempts to replay pending soft
    interrupts as KUAP regions have hardware interrupts enabled.
    
    If a pending interrupt happens to do user access (performance
    interrupts do that), it enables access for a short period of time so
    after returning from the replay, the user access state remains blocked
    and if a user page fault happens - "Bug: Read fault blocked by AMR!"
    appears and SIGSEGV is sent.
    
    An example trace:
      Bug: Read fault blocked by AMR!
      WARNING: CPU: 0 PID: 1603 at /home/aik/p/kernel/arch/powerpc/include/asm/book3s/64/kup-radix.h:145
      CPU: 0 PID: 1603 Comm: amr Not tainted 5.10.0-rc6_v5.10-rc6_a+fstn1 #24
      NIP:  c00000000009ece8 LR: c00000000009ece4 CTR: 0000000000000000
      REGS: c00000000dc63560 TRAP: 0700   Not tainted  (5.10.0-rc6_v5.10-rc6_a+fstn1)
      MSR:  8000000000021033 <SF,ME,IR,DR,RI,LE>  CR: 28002888  XER: 20040000
      CFAR: c0000000001fa928 IRQMASK: 1
      GPR00: c00000000009ece4 c00000000dc637f0 c000000002397600 000000000000001f
      GPR04: c0000000020eb318 0000000000000000 c00000000dc63494 0000000000000027
      GPR08: c00000007fe4de68 c00000000dfe9180 0000000000000000 0000000000000001
      GPR12: 0000000000002000 c0000000030a0000 0000000000000000 0000000000000000
      GPR16: 0000000000000000 0000000000000000 0000000000000000 bfffffffffffffff
      GPR20: 0000000000000000 c0000000134a4020 c0000000019c2218 0000000000000fe0
      GPR24: 0000000000000000 0000000000000000 c00000000d106200 0000000040000000
      GPR28: 0000000000000000 0000000000000300 c00000000dc63910 c000000001946730
      NIP __do_page_fault+0xb38/0xde0
      LR  __do_page_fault+0xb34/0xde0
      Call Trace:
        __do_page_fault+0xb34/0xde0 (unreliable)
        handle_page_fault+0x10/0x2c
      --- interrupt: 300 at strncpy_from_user+0x290/0x440
          LR = strncpy_from_user+0x284/0x440
        strncpy_from_user+0x2f0/0x440 (unreliable)
        getname_flags+0x88/0x2c0
        do_sys_openat2+0x2d4/0x5f0
        do_sys_open+0xcc/0x140
        system_call_exception+0x160/0x240
        system_call_common+0xf0/0x27c
    
    To fix it save/restore the AMR when replaying interrupts, and also
    add a check if AMR was not blocked prior to replaying interrupts.
    
    Originally found by syzkaller.
    
    Fixes: 890274c2dc4c ("powerpc/64s: Implement KUAP for Radix MMU")
    Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxxxx>
    Reviewed-by: Nicholas Piggin <npiggin@xxxxxxxxx>
    [mpe: Use normal commit citation format and add full oops log to
          change log, move kuap_check_amr() into the restore routine to
          avoid warnings about unreconciled IRQ state]
    Signed-off-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20210202091541.36499-1-aik@xxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index cc7a6271b6b4e..e8a548447dd68 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -269,6 +269,31 @@ void replay_soft_interrupts(void)
 	}
 }
 
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP)
+static inline void replay_soft_interrupts_irqrestore(void)
+{
+	unsigned long kuap_state = get_kuap();
+
+	/*
+	 * Check if anything calls local_irq_enable/restore() when KUAP is
+	 * disabled (user access enabled). We handle that case here by saving
+	 * and re-locking AMR but we shouldn't get here in the first place,
+	 * hence the warning.
+	 */
+	kuap_check_amr();
+
+	if (kuap_state != AMR_KUAP_BLOCKED)
+		set_kuap(AMR_KUAP_BLOCKED);
+
+	replay_soft_interrupts();
+
+	if (kuap_state != AMR_KUAP_BLOCKED)
+		set_kuap(kuap_state);
+}
+#else
+#define replay_soft_interrupts_irqrestore() replay_soft_interrupts()
+#endif
+
 notrace void arch_local_irq_restore(unsigned long mask)
 {
 	unsigned char irq_happened;
@@ -332,7 +357,7 @@ notrace void arch_local_irq_restore(unsigned long mask)
 	irq_soft_mask_set(IRQS_ALL_DISABLED);
 	trace_hardirqs_off();
 
-	replay_soft_interrupts();
+	replay_soft_interrupts_irqrestore();
 	local_paca->irq_happened = 0;
 
 	trace_hardirqs_on();



[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