Skip to content

Commit

Permalink
parisc: Fix some apparent put_user() failures
Browse files Browse the repository at this point in the history
After commit 4b9d2a7 ("parisc: Switch user access functions
to signal errors in r29 instead of r8") bash suddenly started
to report those warnings after login:

-bash: cannot set terminal process group (-1): Bad file descriptor
-bash: no job control in this shell

It turned out, that a function call inside a put_user(), e.g.:
put_user(vt_do_kdgkbmode(console), (int __user *)arg);
clobbered the error register (r29) and thus the put_user() call itself
seem to have failed.

Rearrange the C-code to pre-calculate the intermediate value
and then do the put_user().
Additionally prefer the "+" constraint on pu_err and gu_err registers
to tell the compiler that those operands are both read and written by
the assembly instruction.

Reported-by: John David Anglin <[email protected]>
Signed-off-by: Helge Deller <[email protected]>
Fixes: 4b9d2a7 ("parisc: Switch user access functions to signal errors in r29 instead of r8")
Signed-off-by: Helge Deller <[email protected]>
  • Loading branch information
hdeller committed Feb 14, 2022
1 parent b160628 commit dbd0b42
Showing 1 changed file with 15 additions and 14 deletions.
29 changes: 15 additions & 14 deletions arch/parisc/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ struct exception_table_entry {
__asm__("1: " ldx " 0(" sr "%2),%0\n" \
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err)); \
: "=r"(__gu_val), "+r"(__gu_err) \
: "r"(ptr)); \
\
(val) = (__force __typeof__(*(ptr))) __gu_val; \
}
Expand Down Expand Up @@ -123,8 +123,8 @@ struct exception_table_entry {
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
: "=&r"(__gu_tmp.l), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err)); \
: "=&r"(__gu_tmp.l), "+r"(__gu_err) \
: "r"(ptr)); \
\
(val) = __gu_tmp.t; \
}
Expand All @@ -135,13 +135,12 @@ struct exception_table_entry {
#define __put_user_internal(sr, x, ptr) \
({ \
ASM_EXCEPTIONTABLE_VAR(__pu_err); \
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
\
switch (sizeof(*(ptr))) { \
case 1: __put_user_asm(sr, "stb", __x, ptr); break; \
case 2: __put_user_asm(sr, "sth", __x, ptr); break; \
case 4: __put_user_asm(sr, "stw", __x, ptr); break; \
case 8: STD_USER(sr, __x, ptr); break; \
case 1: __put_user_asm(sr, "stb", x, ptr); break; \
case 2: __put_user_asm(sr, "sth", x, ptr); break; \
case 4: __put_user_asm(sr, "stw", x, ptr); break; \
case 8: STD_USER(sr, x, ptr); break; \
default: BUILD_BUG(); \
} \
\
Expand All @@ -150,7 +149,9 @@ struct exception_table_entry {

#define __put_user(x, ptr) \
({ \
__put_user_internal("%%sr3,", x, ptr); \
__typeof__(&*(ptr)) __ptr = ptr; \
__typeof__(*(__ptr)) __x = (__typeof__(*(__ptr)))(x); \
__put_user_internal("%%sr3,", __x, __ptr); \
})

#define __put_kernel_nofault(dst, src, type, err_label) \
Expand Down Expand Up @@ -180,8 +181,8 @@ struct exception_table_entry {
"1: " stx " %2,0(" sr "%1)\n" \
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
: "+r"(__pu_err) \
: "r"(ptr), "r"(x))


#if !defined(CONFIG_64BIT)
Expand All @@ -193,8 +194,8 @@ struct exception_table_entry {
"9:\n" \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
: "=r"(__pu_err) \
: "r"(ptr), "r"(__val), "0"(__pu_err)); \
: "+r"(__pu_err) \
: "r"(ptr), "r"(__val)); \
} while (0)

#endif /* !defined(CONFIG_64BIT) */
Expand Down

0 comments on commit dbd0b42

Please sign in to comment.