From: Helge Deller deller@gmx.de
mainline inclusion from mainline-v5.17-rc1 commit 4b9d2a731c3d22a05c1bccdb11b6e00054ff5fda category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9E2GP CVE: CVE-2024-26706
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Use register r29 instead of register r8 to signal faults when accessing user memory. In case of faults, the fixup routine will store -EFAULT in this register.
This change saves up to 752 bytes on a 32bit kernel, partly because the compiler doesn't need to save and restore the old r8 value on the stack.
bloat-o-meter results for usage with r29 register: add/remove: 0/0 grow/shrink: 23/86 up/down: 228/-980 (-752)
bloat-o-meter results for usage with r28 register: add/remove: 0/0 grow/shrink: 28/83 up/down: 296/-956 (-660)
Signed-off-by: Helge Deller deller@gmx.de Signed-off-by: Cheng Yu serein.chengyu@huawei.com --- arch/parisc/include/asm/uaccess.h | 12 ++++++++---- arch/parisc/mm/fault.c | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index ed2cd4fb479b..d27cecba916e 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -61,9 +61,12 @@ struct exception_table_entry { /* * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry * (with lowest bit set) for which the fault handler in fixup_exception() will - * load -EFAULT into %r8 for a read or write fault, and zeroes the target + * load -EFAULT into %r29 for a read or write fault, and zeroes the target * register in case of a read fault in get_user(). */ +#define ASM_EXCEPTIONTABLE_REG 29 +#define ASM_EXCEPTIONTABLE_VAR(__variable) \ + register long __variable __asm__ ("r29") = 0 #define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\ ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1)
@@ -82,7 +85,7 @@ struct exception_table_entry {
#define __get_user_internal(val, ptr) \ ({ \ - register long __gu_err __asm__ ("r8") = 0; \ + ASM_EXCEPTIONTABLE_VAR(__gu_err); \ \ switch (sizeof(*(ptr))) { \ case 1: __get_user_asm(val, "ldb", ptr); break; \ @@ -140,7 +143,7 @@ struct exception_table_entry {
#define __put_user_internal(x, ptr) \ ({ \ - register long __pu_err __asm__ ("r8") = 0; \ + ASM_EXCEPTIONTABLE_VAR(__pu_err); \ __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ \ switch (sizeof(*(ptr))) { \ @@ -167,7 +170,8 @@ struct exception_table_entry { * gcc knows about, so there are no aliasing issues. These macros must * also be aware that fixups are executed in the context of the fault, * and any registers used there must be listed as clobbers. - * r8 is already listed as err. + * The register holding the possible EFAULT error (ASM_EXCEPTIONTABLE_REG) + * is already listed as input and output register. */
#define __put_user_asm(stx, x, ptr) \ diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 5faa3cff4738..f365986d6a07 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -148,11 +148,11 @@ int fixup_exception(struct pt_regs *regs) * Fix up get_user() and put_user(). * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() sets the least-significant * bit in the relative address of the fixup routine to indicate - * that %r8 should be loaded with -EFAULT to report a userspace - * access error. + * that gr[ASM_EXCEPTIONTABLE_REG] should be loaded with + * -EFAULT to report a userspace access error. */ if (fix->fixup & 1) { - regs->gr[8] = -EFAULT; + regs->gr[ASM_EXCEPTIONTABLE_REG] = -EFAULT;
/* zero target register for get_user() */ if (parisc_acctyp(0, regs->iir) == VM_READ) {