From: Christophe Leroy <christophe.leroy@csgroup.eu> To: Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>, Michael Ellerman <mpe@ellerman.id.au>, npiggin@gmail.com, aneesh.kumar@linux.ibm.com Cc: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: [PATCH v3 1/5] powerpc/book3s64/kuap: Improve error reporting with KUAP Date: Tue, 8 Dec 2020 08:36:58 +0000 (UTC) [thread overview] Message-ID: <0d37490a067840f53fc5b118869917c0aec9ab87.1607416578.git.christophe.leroy@csgroup.eu> (raw) From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> This partially reverts commit eb232b162446 ("powerpc/book3s64/kuap: Improve error reporting with KUAP") and update the fault handler to print [ 55.022514] Kernel attempted to access user page (7e6725b70000) - exploit attempt? (uid: 0) [ 55.022528] BUG: Unable to handle kernel data access on read at 0x7e6725b70000 [ 55.022533] Faulting instruction address: 0xc000000000e8b9bc [ 55.022540] Oops: Kernel access of bad area, sig: 11 [#1] .... when the kernel access userspace address without unlocking AMR. bad_kuap_fault() is added as part of commit 5e5be3aed230 ("powerpc/mm: Detect bad KUAP faults") to catch userspace access incorrectly blocked by AMR. Hence retain the full stack dump there even with hash translation. Also, add a comment explaining the difference between hash and radix. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> --- arch/powerpc/include/asm/book3s/32/kup.h | 4 +-- arch/powerpc/include/asm/book3s/64/kup.h | 34 ++++++++++---------- arch/powerpc/include/asm/kup.h | 4 +-- arch/powerpc/include/asm/nohash/32/kup-8xx.h | 4 +-- arch/powerpc/mm/fault.c | 4 +-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h index b18cd931e325..32fd4452e960 100644 --- a/arch/powerpc/include/asm/book3s/32/kup.h +++ b/arch/powerpc/include/asm/book3s/32/kup.h @@ -177,8 +177,8 @@ static inline void restore_user_access(unsigned long flags) allow_user_access(to, to, end - addr, KUAP_READ_WRITE); } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { unsigned long begin = regs->kuap & 0xf0000000; unsigned long end = regs->kuap << 28; diff --git a/arch/powerpc/include/asm/book3s/64/kup.h b/arch/powerpc/include/asm/book3s/64/kup.h index f2e6dd78d5e2..7075c92c320c 100644 --- a/arch/powerpc/include/asm/book3s/64/kup.h +++ b/arch/powerpc/include/asm/book3s/64/kup.h @@ -353,29 +353,29 @@ static inline void set_kuap(unsigned long value) isync(); } -#define RADIX_KUAP_BLOCK_READ UL(0x4000000000000000) -#define RADIX_KUAP_BLOCK_WRITE UL(0x8000000000000000) - static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) + bool is_write) { if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) return false; - - if (radix_enabled()) { - /* - * Will be a storage protection fault. - * Only check the details of AMR[0] - */ - return WARN((regs->kuap & (is_write ? RADIX_KUAP_BLOCK_WRITE : RADIX_KUAP_BLOCK_READ)), - "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read"); - } /* - * We don't want to WARN here because userspace can setup - * keys such that a kernel access to user address can cause - * fault + * For radix this will be a storage protection fault (DSISR_PROTFAULT). + * For hash this will be a key fault (DSISR_KEYFAULT) */ - return !!(error_code & DSISR_KEYFAULT); + /* + * We do have exception table entry, but accessing the + * userspace results in fault. This could be because we + * didn't unlock the AMR or access is denied by userspace + * using a key value that blocks access. We are only interested + * in catching the use case of accessing without unlocking + * the AMR. Hence check for BLOCK_WRITE/READ against AMR. + */ + if (is_write) { + return WARN(((regs->amr & AMR_KUAP_BLOCK_WRITE) == AMR_KUAP_BLOCK_WRITE), + "Bug: Write fault blocked by AMR!"); + } + return WARN(((regs->amr & AMR_KUAP_BLOCK_READ) == AMR_KUAP_BLOCK_READ), + "Bug: Read fault blocked by AMR!"); } static __always_inline void allow_user_access(void __user *to, const void __user *from, diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index f8ec679bd2de..5a9820c54da9 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -62,8 +62,8 @@ void setup_kuap(bool disabled); #else static inline void setup_kuap(bool disabled) { } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { return false; } diff --git a/arch/powerpc/include/asm/nohash/32/kup-8xx.h b/arch/powerpc/include/asm/nohash/32/kup-8xx.h index 7bdd9e5b63ed..567cdc557402 100644 --- a/arch/powerpc/include/asm/nohash/32/kup-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/kup-8xx.h @@ -60,8 +60,8 @@ static inline void restore_user_access(unsigned long flags) mtspr(SPRN_MD_AP, flags); } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000), "Bug: fault blocked by AP register !"); diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index c91621df0c61..b12595102525 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -210,7 +210,7 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code, return true; } - if (!is_exec && address < TASK_SIZE && (error_code & DSISR_PROTFAULT) && + if (!is_exec && address < TASK_SIZE && (error_code & (DSISR_PROTFAULT | DSISR_KEYFAULT)) && !search_exception_tables(regs->nip)) { pr_crit_ratelimited("Kernel attempted to access user page (%lx) - exploit attempt? (uid: %d)\n", address, @@ -227,7 +227,7 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code, // Read/write fault in a valid region (the exception table search passed // above), but blocked by KUAP is bad, it can never succeed. - if (bad_kuap_fault(regs, address, is_write, error_code)) + if (bad_kuap_fault(regs, address, is_write)) return true; // What's left? Kernel fault on user in well defined regions (extable -- 2.25.0
WARNING: multiple messages have this Message-ID (diff)
From: Christophe Leroy <christophe.leroy@csgroup.eu> To: Benjamin Herrenschmidt <benh@kernel.crashing.org>, Paul Mackerras <paulus@samba.org>, Michael Ellerman <mpe@ellerman.id.au>, npiggin@gmail.com, aneesh.kumar@linux.ibm.com Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/5] powerpc/book3s64/kuap: Improve error reporting with KUAP Date: Tue, 8 Dec 2020 08:36:58 +0000 (UTC) [thread overview] Message-ID: <0d37490a067840f53fc5b118869917c0aec9ab87.1607416578.git.christophe.leroy@csgroup.eu> (raw) From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> This partially reverts commit eb232b162446 ("powerpc/book3s64/kuap: Improve error reporting with KUAP") and update the fault handler to print [ 55.022514] Kernel attempted to access user page (7e6725b70000) - exploit attempt? (uid: 0) [ 55.022528] BUG: Unable to handle kernel data access on read at 0x7e6725b70000 [ 55.022533] Faulting instruction address: 0xc000000000e8b9bc [ 55.022540] Oops: Kernel access of bad area, sig: 11 [#1] .... when the kernel access userspace address without unlocking AMR. bad_kuap_fault() is added as part of commit 5e5be3aed230 ("powerpc/mm: Detect bad KUAP faults") to catch userspace access incorrectly blocked by AMR. Hence retain the full stack dump there even with hash translation. Also, add a comment explaining the difference between hash and radix. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> --- arch/powerpc/include/asm/book3s/32/kup.h | 4 +-- arch/powerpc/include/asm/book3s/64/kup.h | 34 ++++++++++---------- arch/powerpc/include/asm/kup.h | 4 +-- arch/powerpc/include/asm/nohash/32/kup-8xx.h | 4 +-- arch/powerpc/mm/fault.c | 4 +-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h index b18cd931e325..32fd4452e960 100644 --- a/arch/powerpc/include/asm/book3s/32/kup.h +++ b/arch/powerpc/include/asm/book3s/32/kup.h @@ -177,8 +177,8 @@ static inline void restore_user_access(unsigned long flags) allow_user_access(to, to, end - addr, KUAP_READ_WRITE); } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { unsigned long begin = regs->kuap & 0xf0000000; unsigned long end = regs->kuap << 28; diff --git a/arch/powerpc/include/asm/book3s/64/kup.h b/arch/powerpc/include/asm/book3s/64/kup.h index f2e6dd78d5e2..7075c92c320c 100644 --- a/arch/powerpc/include/asm/book3s/64/kup.h +++ b/arch/powerpc/include/asm/book3s/64/kup.h @@ -353,29 +353,29 @@ static inline void set_kuap(unsigned long value) isync(); } -#define RADIX_KUAP_BLOCK_READ UL(0x4000000000000000) -#define RADIX_KUAP_BLOCK_WRITE UL(0x8000000000000000) - static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) + bool is_write) { if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) return false; - - if (radix_enabled()) { - /* - * Will be a storage protection fault. - * Only check the details of AMR[0] - */ - return WARN((regs->kuap & (is_write ? RADIX_KUAP_BLOCK_WRITE : RADIX_KUAP_BLOCK_READ)), - "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read"); - } /* - * We don't want to WARN here because userspace can setup - * keys such that a kernel access to user address can cause - * fault + * For radix this will be a storage protection fault (DSISR_PROTFAULT). + * For hash this will be a key fault (DSISR_KEYFAULT) */ - return !!(error_code & DSISR_KEYFAULT); + /* + * We do have exception table entry, but accessing the + * userspace results in fault. This could be because we + * didn't unlock the AMR or access is denied by userspace + * using a key value that blocks access. We are only interested + * in catching the use case of accessing without unlocking + * the AMR. Hence check for BLOCK_WRITE/READ against AMR. + */ + if (is_write) { + return WARN(((regs->amr & AMR_KUAP_BLOCK_WRITE) == AMR_KUAP_BLOCK_WRITE), + "Bug: Write fault blocked by AMR!"); + } + return WARN(((regs->amr & AMR_KUAP_BLOCK_READ) == AMR_KUAP_BLOCK_READ), + "Bug: Read fault blocked by AMR!"); } static __always_inline void allow_user_access(void __user *to, const void __user *from, diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index f8ec679bd2de..5a9820c54da9 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -62,8 +62,8 @@ void setup_kuap(bool disabled); #else static inline void setup_kuap(bool disabled) { } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { return false; } diff --git a/arch/powerpc/include/asm/nohash/32/kup-8xx.h b/arch/powerpc/include/asm/nohash/32/kup-8xx.h index 7bdd9e5b63ed..567cdc557402 100644 --- a/arch/powerpc/include/asm/nohash/32/kup-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/kup-8xx.h @@ -60,8 +60,8 @@ static inline void restore_user_access(unsigned long flags) mtspr(SPRN_MD_AP, flags); } -static inline bool bad_kuap_fault(struct pt_regs *regs, unsigned long address, - bool is_write, unsigned long error_code) +static inline bool +bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write) { return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xff000000), "Bug: fault blocked by AP register !"); diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index c91621df0c61..b12595102525 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -210,7 +210,7 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code, return true; } - if (!is_exec && address < TASK_SIZE && (error_code & DSISR_PROTFAULT) && + if (!is_exec && address < TASK_SIZE && (error_code & (DSISR_PROTFAULT | DSISR_KEYFAULT)) && !search_exception_tables(regs->nip)) { pr_crit_ratelimited("Kernel attempted to access user page (%lx) - exploit attempt? (uid: %d)\n", address, @@ -227,7 +227,7 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code, // Read/write fault in a valid region (the exception table search passed // above), but blocked by KUAP is bad, it can never succeed. - if (bad_kuap_fault(regs, address, is_write, error_code)) + if (bad_kuap_fault(regs, address, is_write)) return true; // What's left? Kernel fault on user in well defined regions (extable -- 2.25.0
next reply other threads:[~2020-12-08 8:37 UTC|newest] Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-12-08 8:36 Christophe Leroy [this message] 2020-12-08 8:36 ` [PATCH v3 1/5] powerpc/book3s64/kuap: Improve error reporting with KUAP Christophe Leroy 2020-12-08 8:36 ` [PATCH v3 2/5] powerpc/mm: sanity_check_fault() should work for all, not only BOOK3S Christophe Leroy 2020-12-08 8:36 ` Christophe Leroy 2020-12-08 8:37 ` [PATCH v3 3/5] powerpc/fault: Unnest definition of page_fault_is_write() and page_fault_is_bad() Christophe Leroy 2020-12-08 8:37 ` Christophe Leroy 2020-12-08 8:37 ` [PATCH v3 4/5] powerpc/fault: Avoid heavy search_exception_tables() verification Christophe Leroy 2020-12-08 8:37 ` Christophe Leroy 2020-12-08 13:00 ` Aneesh Kumar K.V 2020-12-08 13:00 ` Aneesh Kumar K.V 2020-12-08 14:26 ` Christophe Leroy 2020-12-08 14:26 ` Christophe Leroy 2020-12-08 14:31 ` Aneesh Kumar K.V 2020-12-08 14:31 ` Aneesh Kumar K.V 2020-12-08 14:52 ` Aneesh Kumar K.V 2020-12-08 14:52 ` Aneesh Kumar K.V 2020-12-08 15:07 ` Christophe Leroy 2020-12-08 15:07 ` Christophe Leroy 2020-12-09 5:34 ` Christophe Leroy 2020-12-08 8:37 ` [PATCH v3 5/5] powerpc/fault: Perform exception fixup in do_page_fault() Christophe Leroy 2020-12-08 8:37 ` Christophe Leroy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=0d37490a067840f53fc5b118869917c0aec9ab87.1607416578.git.christophe.leroy@csgroup.eu \ --to=christophe.leroy@csgroup.eu \ --cc=aneesh.kumar@linux.ibm.com \ --cc=benh@kernel.crashing.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linuxppc-dev@lists.ozlabs.org \ --cc=mpe@ellerman.id.au \ --cc=npiggin@gmail.com \ --cc=paulus@samba.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.