Skip to content

Commit 89f686a

Browse files
danglin44hdeller
authored andcommitted
parisc: Revise __get_user() to probe user read access
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 <[email protected]> Signed-off-by: Helge Deller <[email protected]> Cc: [email protected] # v5.12+
1 parent f6334f4 commit 89f686a

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

arch/parisc/include/asm/uaccess.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,24 @@
4242
__gu_err; \
4343
})
4444

45-
#define __get_user(val, ptr) \
46-
({ \
47-
__get_user_internal(SR_USER, val, ptr); \
45+
#define __probe_user_internal(sr, error, ptr) \
46+
({ \
47+
__asm__("\tproberi (%%sr%1,%2),%3,%0\n" \
48+
"\tcmpiclr,= 1,%0,%0\n" \
49+
"\tldi %4,%0\n" \
50+
: "=r"(error) \
51+
: "i"(sr), "r"(ptr), "i"(PRIV_USER), \
52+
"i"(-EFAULT)); \
53+
})
54+
55+
#define __get_user(val, ptr) \
56+
({ \
57+
register long __gu_err; \
58+
\
59+
__gu_err = __get_user_internal(SR_USER, val, ptr); \
60+
if (likely(!__gu_err)) \
61+
__probe_user_internal(SR_USER, __gu_err, ptr); \
62+
__gu_err; \
4863
})
4964

5065
#define __get_user_asm(sr, val, ldx, ptr) \

0 commit comments

Comments
 (0)