mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
parisc: Fix random data corruption from exception handler
The current exception handler implementation, which assists when accessing user space memory, may exhibit random data corruption if the compiler decides to use a different register than the specified register %r29 (defined in ASM_EXCEPTIONTABLE_REG) for the error code. If the compiler choose another register, the fault handler will nevertheless store -EFAULT into %r29 and thus trash whatever this register is used for. Looking at the assembly I found that this happens sometimes in emulate_ldd(). To solve the issue, the easiest solution would be if it somehow is possible to tell the fault handler which register is used to hold the error code. Using %0 or %1 in the inline assembly is not posssible as it will show up as e.g. %r29 (with the "%r" prefix), which the GNU assembler can not convert to an integer. This patch takes another, better and more flexible approach: We extend the __ex_table (which is out of the execution path) by one 32-word. In this word we tell the compiler to insert the assembler instruction "or %r0,%r0,%reg", where %reg references the register which the compiler choosed for the error return code. In case of an access failure, the fault handler finds the __ex_table entry and can examine the opcode. The used register is encoded in the lowest 5 bits, and the fault handler can then store -EFAULT into this register. Since we extend the __ex_table to 3 words we can't use the BUILDTIME_TABLE_SORT config option any longer. Signed-off-by: Helge Deller <deller@gmx.de> Cc: <stable@vger.kernel.org> # v6.0+
This commit is contained in:
@@ -854,7 +854,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
|
||||
#endif
|
||||
" fic,m %3(%4,%0)\n"
|
||||
"2: sync\n"
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b)
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
|
||||
: "+r" (start), "+r" (error)
|
||||
: "r" (end), "r" (dcache_stride), "i" (SR_USER));
|
||||
}
|
||||
@@ -869,7 +869,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes,
|
||||
#endif
|
||||
" fdc,m %3(%4,%0)\n"
|
||||
"2: sync\n"
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b)
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
|
||||
: "+r" (start), "+r" (error)
|
||||
: "r" (end), "r" (icache_stride), "i" (SR_USER));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user