-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
parisc: Fix random data corruption from exception handler
commit 8b1d72395635af45410b66cc4c4ab37a12c4a831 upstream. 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 <[email protected]> Cc: <[email protected]> # v6.0+ Signed-off-by: Greg Kroah-Hartman <[email protected]>
- Loading branch information
1 parent
248e412
commit db29e5c
Showing
7 changed files
with
105 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __PARISC_EXTABLE_H | ||
#define __PARISC_EXTABLE_H | ||
|
||
#include <asm/ptrace.h> | ||
#include <linux/compiler.h> | ||
|
||
/* | ||
* The exception table consists of three addresses: | ||
* | ||
* - A relative address to the instruction that is allowed to fault. | ||
* - A relative address at which the program should continue (fixup routine) | ||
* - An asm statement which specifies which CPU register will | ||
* receive -EFAULT when an exception happens if the lowest bit in | ||
* the fixup address is set. | ||
* | ||
* Note: The register specified in the err_opcode instruction will be | ||
* modified at runtime if a fault happens. Register %r0 will be ignored. | ||
* | ||
* Since relative addresses are used, 32bit values are sufficient even on | ||
* 64bit kernel. | ||
*/ | ||
|
||
struct pt_regs; | ||
int fixup_exception(struct pt_regs *regs); | ||
|
||
#define ARCH_HAS_RELATIVE_EXTABLE | ||
struct exception_table_entry { | ||
int insn; /* relative address of insn that is allowed to fault. */ | ||
int fixup; /* relative address of fixup routine */ | ||
int err_opcode; /* sample opcode with register which holds error code */ | ||
}; | ||
|
||
#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr, opcode )\ | ||
".section __ex_table,\"aw\"\n" \ | ||
".align 4\n" \ | ||
".word (" #fault_addr " - .), (" #except_addr " - .)\n" \ | ||
opcode "\n" \ | ||
".previous\n" | ||
|
||
/* | ||
* 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 on fault into the register specified by the err_opcode instruction, | ||
* and zeroes the target register in case of a read fault in get_user(). | ||
*/ | ||
#define ASM_EXCEPTIONTABLE_VAR(__err_var) \ | ||
int __err_var = 0 | ||
#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr, register )\ | ||
ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1, "or %%r0,%%r0," register) | ||
|
||
static inline void swap_ex_entry_fixup(struct exception_table_entry *a, | ||
struct exception_table_entry *b, | ||
struct exception_table_entry tmp, | ||
int delta) | ||
{ | ||
a->fixup = b->fixup + delta; | ||
b->fixup = tmp.fixup - delta; | ||
a->err_opcode = b->err_opcode; | ||
b->err_opcode = tmp.err_opcode; | ||
} | ||
#define swap_ex_entry_fixup swap_ex_entry_fixup | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters