powerpc/kuap: Allow kernel thread to access userspace after kthread_use_mm
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.
current_thread_amr/iamr() are updated, because we use them in the
below stack.
....
[ 530.710838] CPU: 13 PID: 5587 Comm: io_wqe_worker-0 Tainted: G D 5.11.0-rc6+ #3
....
NIP [c0000000000aa0c8] pkey_access_permitted+0x28/0x90
LR [c0000000004b9278] gup_pte_range+0x188/0x420
--- interrupt: 700
[c00000001c4ef3f0] [0000000000000000] 0x0 (unreliable)
[c00000001c4ef490] [c0000000004bd39c] gup_pgd_range+0x3ac/0xa20
[c00000001c4ef5a0] [c0000000004bdd44] internal_get_user_pages_fast+0x334/0x410
[c00000001c4ef620] [c000000000852028] iov_iter_get_pages+0xf8/0x5c0
[c00000001c4ef6a0] [c0000000007da44c] bio_iov_iter_get_pages+0xec/0x700
[c00000001c4ef770] [c0000000006a325c] iomap_dio_bio_actor+0x2ac/0x4f0
[c00000001c4ef810] [c00000000069cd94] iomap_apply+0x2b4/0x740
[c00000001c4ef920] [c0000000006a38b8] __iomap_dio_rw+0x238/0x5c0
[c00000001c4ef9d0] [c0000000006a3c60] iomap_dio_rw+0x20/0x80
[c00000001c4ef9f0] [c008000001927a30] xfs_file_dio_aio_write+0x1f8/0x650 [xfs]
[c00000001c4efa60] [c0080000019284dc] xfs_file_write_iter+0xc4/0x130 [xfs]
[c00000001c4efa90] [c000000000669984] io_write+0x104/0x4b0
[c00000001c4efbb0] [c00000000066cea4] io_issue_sqe+0x3d4/0xf50
[c00000001c4efc60] [c000000000670200] io_wq_submit_work+0xb0/0x2f0
[c00000001c4efcb0] [c000000000674268] io_worker_handle_work+0x248/0x4a0
[c00000001c4efd30] [c0000000006746e8] io_wqe_worker+0x228/0x2a0
[c00000001c4efda0] [c00000000019d994] kthread+0x1b4/0x1c0
Fixes: 48a8ab4eeb
("powerpc/book3s64/pkeys: Don't update SPRN_AMR when in kernel mode.")
Reported-by: Zorro Lang <zlang@redhat.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210206025634.521979-1-aneesh.kumar@linux.ibm.com
This commit is contained in:
parent
24321ac668
commit
8c511eff18
|
@ -199,25 +199,31 @@ DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_PKEY
|
#ifdef CONFIG_PPC_PKEY
|
||||||
|
|
||||||
|
extern u64 __ro_after_init default_uamor;
|
||||||
|
extern u64 __ro_after_init default_amr;
|
||||||
|
extern u64 __ro_after_init default_iamr;
|
||||||
|
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
/*
|
/* usage of kthread_use_mm() should inherit the
|
||||||
* For kernel thread that doesn't have thread.regs return
|
* AMR value of the operating address space. But, the AMR value is
|
||||||
* default AMR/IAMR values.
|
* 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.
|
||||||
*/
|
*/
|
||||||
static inline u64 current_thread_amr(void)
|
static inline u64 current_thread_amr(void)
|
||||||
{
|
{
|
||||||
if (current->thread.regs)
|
if (current->thread.regs)
|
||||||
return current->thread.regs->amr;
|
return current->thread.regs->amr;
|
||||||
return AMR_KUAP_BLOCKED;
|
return default_amr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u64 current_thread_iamr(void)
|
static inline u64 current_thread_iamr(void)
|
||||||
{
|
{
|
||||||
if (current->thread.regs)
|
if (current->thread.regs)
|
||||||
return current->thread.regs->iamr;
|
return current->thread.regs->iamr;
|
||||||
return AMR_KUEP_BLOCKED;
|
return default_iamr;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_PKEY */
|
#endif /* CONFIG_PPC_PKEY */
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
#include <asm/book3s/64/hash-pkey.h>
|
#include <asm/book3s/64/hash-pkey.h>
|
||||||
|
|
||||||
extern u64 __ro_after_init default_uamor;
|
|
||||||
extern u64 __ro_after_init default_amr;
|
|
||||||
extern u64 __ro_after_init default_iamr;
|
|
||||||
|
|
||||||
static inline u64 vmflag_to_pte_pkey_bits(u64 vm_flags)
|
static inline u64 vmflag_to_pte_pkey_bits(u64 vm_flags)
|
||||||
{
|
{
|
||||||
if (!mmu_has_feature(MMU_FTR_PKEY))
|
if (!mmu_has_feature(MMU_FTR_PKEY))
|
||||||
|
|
|
@ -31,6 +31,7 @@ static u32 initial_allocation_mask __ro_after_init;
|
||||||
u64 default_amr __ro_after_init = ~0x0UL;
|
u64 default_amr __ro_after_init = ~0x0UL;
|
||||||
u64 default_iamr __ro_after_init = 0x5555555555555555UL;
|
u64 default_iamr __ro_after_init = 0x5555555555555555UL;
|
||||||
u64 default_uamor __ro_after_init;
|
u64 default_uamor __ro_after_init;
|
||||||
|
EXPORT_SYMBOL(default_amr);
|
||||||
/*
|
/*
|
||||||
* Key used to implement PROT_EXEC mmap. Denies READ/WRITE
|
* Key used to implement PROT_EXEC mmap. Denies READ/WRITE
|
||||||
* We pick key 2 because 0 is special key and 1 is reserved as per ISA.
|
* We pick key 2 because 0 is special key and 1 is reserved as per ISA.
|
||||||
|
|
Loading…
Reference in a new issue