[PATCH] powerpc/fault: fix wrong KUAP fault for IO_URING

Zorro Lang zlang at redhat.com
Thu Jan 28 01:56:48 AEDT 2021


On powerpc, io_uring test hit below KUAP fault on __do_page_fault.
The fail source line is:

  if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address, is_write)))
      return SIGSEGV;

The is_user() is based on user_mod(regs) only. This's not suit for
io_uring, where the helper thread can assume the user app identity
and could perform this fault just fine. So turn to use mm to decide
if this is valid or not.

[  556.472666] ------------[ cut here ]------------
[  556.472686] Bug: Read fault blocked by KUAP!
[  556.472697] WARNING: CPU: 1 PID: 101841 at arch/powerpc/mm/fault.c:229 __do_page_fault+0x6b4/0xcd0
[  556.472728] Modules linked in: bonding rfkill sunrpc pseries_rng xts uio_pdrv_genirq vmx_crypto uio ip_tables xfs libcrc32c sd_mod t10_pi sg ibmvscsi ibmveth scsi_transport_srp
[  556.472816] CPU: 1 PID: 101841 Comm: io_wqe_worker-0 Tainted: G        W         5.11.0-rc3+ #2
[  556.472830] NIP:  c00000000009e7e4 LR: c00000000009e7e0 CTR: 0000000000000000
[  556.472842] REGS: c000000016367090 TRAP: 0700   Tainted: G        W          (5.11.0-rc3+)
[  556.472853] MSR:  8000000000021033 <SF,ME,IR,DR,RI,LE>  CR: 48022424  XER: 00000001
[  556.472901] CFAR: c0000000001822ac IRQMASK: 1
               GPR00: c00000000009e7e0 c000000016367330 c0000000023fc300 0000000000000020
               GPR04: c000000001e3c2b8 0000000000000001 0000000000000027 c0000007fbcccc90
               GPR08: 0000000000000023 0000000000000000 c000000024ed0900 fffffffffc464a58
               GPR12: 0000000000002000 c00000001ecaf280 c0000000001caee8 c000000014d547c0
               GPR16: 0000000000000000 0000000000000000 0000000000000000 c000000002454018
               GPR20: c000000001336480 bfffffffffffffff 0000000000000000 c00000000b0e5800
               GPR24: a8aaaaaaaaaaaaaa 0000000000000000 0000000000200000 c00000002cc38880
               GPR28: 000001000e3c9310 c0000000013424c0 c0000000163674a0 c000000001e0d2c0
[  556.473125] NIP [c00000000009e7e4] __do_page_fault+0x6b4/0xcd0
[  556.473139] LR [c00000000009e7e0] __do_page_fault+0x6b0/0xcd0
[  556.473152] Call Trace:
[  556.473168] [c000000016367330] [c00000000009e7e0] __do_page_fault+0x6b0/0xcd0 (unreliable)
[  556.473198] [c0000000163673e0] [c00000000009ee3c] do_page_fault+0x3c/0x120
[  556.473216] [c000000016367430] [c00000000000c848] handle_page_fault+0x10/0x2c
[  556.473232] --- interrupt: 300 at iov_iter_fault_in_readable+0x148/0x6f0
[  556.473245] NIP:  c0000000008e8228 LR: c0000000008e834c CTR: 0000000000000000
[  556.473257] REGS: c0000000163674a0 TRAP: 0300   Tainted: G        W          (5.11.0-rc3+)
[  556.473268] MSR:  800000000280b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE>  CR: 44008482  XER: 00000001
[  556.473339] CFAR: c0000000008e81f0 DAR: 000001000e3c9310 DSISR: 00200000 IRQMASK: 0
               GPR00: c0000000008e834c c000000016367740 c0000000023fc300 0000000000000000
               GPR04: c00000002cc389e0 0000000000000001 00000007fa4b0000 c0000000025bc520
               GPR08: 00000007fa4b0000 0000000000000200 fcffffffffffffff ffffffffffea2ad8
               GPR12: 0000000000008000 c00000001ecaf280 c0000000001caee8 c000000014d547c0
               GPR16: 0000000000000000 0000000000000000 0000000000000000 c000000002454018
               GPR20: c000000001336480 bfffffffffffffff 0000000000000000 c00000000b0e5800
               GPR24: a8aaaaaaaaaaaaaa fcffffffffffffff 00000000000004b1 00000000000004b1
               GPR28: c00000000b0e5888 000001000e3c97c0 0000000000000000 000001000e3c9310
[  556.473667] NIP [c0000000008e8228] iov_iter_fault_in_readable+0x148/0x6f0
[  556.473688] LR [c0000000008e834c] iov_iter_fault_in_readable+0x26c/0x6f0
[  556.473708] --- interrupt: 300
[  556.473722] [c0000000163677e0] [c0000000007154a0] iomap_write_actor+0xc0/0x280
[  556.473770] [c000000016367880] [c00000000070fc94] iomap_apply+0x1c4/0x780
[  556.473804] [c000000016367990] [c000000000710330] iomap_file_buffered_write+0xa0/0x120
[  556.473839] [c0000000163679e0] [c00800000040791c] xfs_file_buffered_aio_write+0x314/0x5e0 [xfs]
[  556.474053] [c000000016367a90] [c0000000006d74bc] io_write+0x10c/0x460
[  556.474101] [c000000016367bb0] [c0000000006d80e4] io_issue_sqe+0x8d4/0x1200
[  556.474132] [c000000016367c70] [c0000000006d8ad0] io_wq_submit_work+0xc0/0x250
[  556.474161] [c000000016367cb0] [c0000000006e2578] io_worker_handle_work+0x498/0x800
[  556.474192] [c000000016367d40] [c0000000006e2cdc] io_wqe_worker+0x3fc/0x4f0
[  556.474223] [c000000016367da0] [c0000000001cb0a4] kthread+0x1c4/0x1d0
[  556.474254] [c000000016367e10] [c00000000000dbf0] ret_from_kernel_thread+0x5c/0x6c
[  556.474286] Instruction dump:
[  556.474310] e87e0100 481287f1 60000000 2fa30000 419e01ec 408e0400 3c82fef4 388461d0
[  556.474395] 3c62fef4 386362d0 480e3a69 60000000 <0fe00000> 3860000b 4bfffa08 3d220006
[  556.474479] irq event stamp: 1280
[  556.474505] hardirqs last  enabled at (1279): [<c0000000005a0104>] __slab_free+0x3e4/0x570
[  556.474540] hardirqs last disabled at (1280): [<c000000000008a04>] data_access_common_virt+0x1a4/0x1c0
[  556.474565] softirqs last  enabled at (536): [<c00000000107cdfc>] __do_softirq+0x6ac/0x7f4
[  556.474590] softirqs last disabled at (437): [<c00000000019179c>] irq_exit+0x2ec/0x320
[  556.474615] ---[ end trace 4c1967c400992302 ]---

Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=211151
Suggested-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Zorro Lang <zlang at redhat.com>
---

Hi,

Thanks to Jens reviewed this bug report from io_uring side, and then suggest this
fix. But we're not expert of powerpc, so report this bug to powerpc maillist to
get more review.

I've tested this patch, I can't reproduce this bug after merge this patch. And
can reproduce it after remove this patch.

Thanks,
Zorro

 arch/powerpc/mm/fault.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 8961b44f350c..5a4d6af04c99 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -417,9 +417,12 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
 	/*
 	 * The kernel should never take an execute fault nor should it
 	 * take a page fault to a kernel address or a page fault to a user
-	 * address outside of dedicated places
+	 * address outside of dedicated places. Use mm to decide if this is
+	 * valid or not, it's perfectly legitimate to have a kernel thread
+	 * take a fault as long as it's performed kthread_use_mm() prior. An
+	 * example of that would be io_uring helper threads.
 	 */
-	if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address, is_write)))
+	if (unlikely(!mm && bad_kernel_fault(regs, error_code, address, is_write)))
 		return SIGSEGV;
 
 	/*
-- 
2.29.2



More information about the Linuxppc-dev mailing list