This fix the bad fault reported by KUAP when io_wqe_worker access userspace.
Bug: Read fault blocked by KUAP! WARNING: CPU: 1 PID: 101841 at arch/powerpc/mm/fault.c:229 __do_page_fault+0x6b4/0xcd0 NIP [c00000000009e7e4] __do_page_fault+0x6b4/0xcd0 LR [c00000000009e7e0] __do_page_fault+0x6b0/0xcd0 .......... Call Trace: [c000000016367330] [c00000000009e7e0] __do_page_fault+0x6b0/0xcd0 (unreliable) [c0000000163673e0] [c00000000009ee3c] do_page_fault+0x3c/0x120 [c000000016367430] [c00000000000c848] handle_page_fault+0x10/0x2c --- interrupt: 300 at iov_iter_fault_in_readable+0x148/0x6f0 .......... NIP [c0000000008e8228] iov_iter_fault_in_readable+0x148/0x6f0 LR [c0000000008e834c] iov_iter_fault_in_readable+0x26c/0x6f0 interrupt: 300 [c0000000163677e0] [c0000000007154a0] iomap_write_actor+0xc0/0x280 [c000000016367880] [c00000000070fc94] iomap_apply+0x1c4/0x780 [c000000016367990] [c000000000710330] iomap_file_buffered_write+0xa0/0x120 [c0000000163679e0] [c00800000040791c] xfs_file_buffered_aio_write+0x314/0x5e0 [xfs] [c000000016367a90] [c0000000006d74bc] io_write+0x10c/0x460 [c000000016367bb0] [c0000000006d80e4] io_issue_sqe+0x8d4/0x1200 [c000000016367c70] [c0000000006d8ad0] io_wq_submit_work+0xc0/0x250 [c000000016367cb0] [c0000000006e2578] io_worker_handle_work+0x498/0x800 [c000000016367d40] [c0000000006e2cdc] io_wqe_worker+0x3fc/0x4f0 [c000000016367da0] [c0000000001cb0a4] kthread+0x1c4/0x1d0 [c000000016367e10] [c00000000000dbf0] ret_from_kernel_thread+0x5c/0x6c The kernel consider thread AMR value for kernel thread to be AMR_KUAP_BLOCKED. Hence access to userspace is denied. This of course not correct and we should allow userspace access after kthread_use_mm(). To be precise, kthread_use_mm() should inherit the AMR value of the operating address space. But, the AMR value is thread-specific and we inherit the address space and not thread access restrictions. Because of this ignore AMR value when accessing userspace via kernel thread. Cc: Zorro Lang <zl...@redhat.com> Cc: Jens Axboe <ax...@kernel.dk> Cc: Christophe Leroy <christophe.le...@csgroup.eu> Cc: Nicholas Piggin <npig...@gmail.com> Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com> --- arch/powerpc/include/asm/book3s/64/kup.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/kup.h b/arch/powerpc/include/asm/book3s/64/kup.h index f50f72e535aa..2064621ae7b6 100644 --- a/arch/powerpc/include/asm/book3s/64/kup.h +++ b/arch/powerpc/include/asm/book3s/64/kup.h @@ -202,22 +202,16 @@ DECLARE_STATIC_KEY_FALSE(uaccess_flush_key); #include <asm/mmu.h> #include <asm/ptrace.h> -/* - * For kernel thread that doesn't have thread.regs return - * default AMR/IAMR values. - */ static inline u64 current_thread_amr(void) { - if (current->thread.regs) - return current->thread.regs->amr; - return AMR_KUAP_BLOCKED; + VM_BUG_ON(!current->thread.regs); + return current->thread.regs->amr; } static inline u64 current_thread_iamr(void) { - if (current->thread.regs) - return current->thread.regs->iamr; - return AMR_KUEP_BLOCKED; + VM_BUG_ON(!current->thread.regs); + return current->thread.regs->iamr; } #endif /* CONFIG_PPC_PKEY */ @@ -384,7 +378,14 @@ static __always_inline void allow_user_access(void __user *to, const void __user // This is written so we can resolve to a single case at build time BUILD_BUG_ON(!__builtin_constant_p(dir)); - if (mmu_has_feature(MMU_FTR_PKEY)) + /* + * Kernel threads may access user mm with kthread_use_mm() but + * can't use current_thread_amr because they have thread.regs==NULL, + * but they have no pkeys. + */ + if (current->flags & PF_KTHREAD) + thread_amr = 0; + else if (mmu_has_feature(MMU_FTR_PKEY)) thread_amr = current_thread_amr(); if (dir == KUAP_READ) -- 2.29.2