| From 89f686a0fb6e473a876a9a60a13aec67a62b9a7e Mon Sep 17 00:00:00 2001 |
| From: John David Anglin <dave.anglin@bell.net> |
| Date: Fri, 25 Jul 2025 13:51:32 -0400 |
| Subject: parisc: Revise __get_user() to probe user read access |
| |
| From: John David Anglin <dave.anglin@bell.net> |
| |
| commit 89f686a0fb6e473a876a9a60a13aec67a62b9a7e upstream. |
| |
| Because of the way read access support is implemented, read access |
| interruptions are only triggered at privilege levels 2 and 3. The |
| kernel executes at privilege level 0, so __get_user() never triggers |
| a read access interruption (code 26). Thus, it is currently possible |
| for user code to access a read protected address via a system call. |
| |
| Fix this by probing read access rights at privilege level 3 (PRIV_USER) |
| and setting __gu_err to -EFAULT (-14) if access isn't allowed. |
| |
| Note the cmpiclr instruction does a 32-bit compare because COND macro |
| doesn't work inside asm. |
| |
| Signed-off-by: John David Anglin <dave.anglin@bell.net> |
| Signed-off-by: Helge Deller <deller@gmx.de> |
| Cc: stable@vger.kernel.org # v5.12+ |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/parisc/include/asm/uaccess.h | 21 ++++++++++++++++++--- |
| 1 file changed, 18 insertions(+), 3 deletions(-) |
| |
| --- a/arch/parisc/include/asm/uaccess.h |
| +++ b/arch/parisc/include/asm/uaccess.h |
| @@ -42,9 +42,24 @@ |
| __gu_err; \ |
| }) |
| |
| -#define __get_user(val, ptr) \ |
| -({ \ |
| - __get_user_internal(SR_USER, val, ptr); \ |
| +#define __probe_user_internal(sr, error, ptr) \ |
| +({ \ |
| + __asm__("\tproberi (%%sr%1,%2),%3,%0\n" \ |
| + "\tcmpiclr,= 1,%0,%0\n" \ |
| + "\tldi %4,%0\n" \ |
| + : "=r"(error) \ |
| + : "i"(sr), "r"(ptr), "i"(PRIV_USER), \ |
| + "i"(-EFAULT)); \ |
| +}) |
| + |
| +#define __get_user(val, ptr) \ |
| +({ \ |
| + register long __gu_err; \ |
| + \ |
| + __gu_err = __get_user_internal(SR_USER, val, ptr); \ |
| + if (likely(!__gu_err)) \ |
| + __probe_user_internal(SR_USER, __gu_err, ptr); \ |
| + __gu_err; \ |
| }) |
| |
| #define __get_user_asm(sr, val, ldx, ptr) \ |