Skip to content

Commit 653884f

Browse files
kristina-martsenkoctmarinas
authored andcommitted
arm64: extable: Add fixup handling for uaccess CPY* instructions
A subsequent patch will use CPY* instructions to copy between user and kernel memory. Add a new exception fixup type to avoid fixing up faults on kernel memory accesses, in order to make it easier to debug kernel bugs and to keep the same behavior as with regular loads/stores. Signed-off-by: Kristina Martšenko <kristina.martsenko@arm.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20250228170006.390100-2-kristina.martsenko@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 0ad2507 commit 653884f

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

arch/arm64/include/asm/asm-extable.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#define EX_TYPE_BPF 1
1010
#define EX_TYPE_UACCESS_ERR_ZERO 2
1111
#define EX_TYPE_KACCESS_ERR_ZERO 3
12-
#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD 4
12+
#define EX_TYPE_UACCESS_CPY 4
13+
#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD 5
1314

1415
/* Data fields for EX_TYPE_UACCESS_ERR_ZERO */
1516
#define EX_DATA_REG_ERR_SHIFT 0
@@ -23,6 +24,9 @@
2324
#define EX_DATA_REG_ADDR_SHIFT 5
2425
#define EX_DATA_REG_ADDR GENMASK(9, 5)
2526

27+
/* Data fields for EX_TYPE_UACCESS_CPY */
28+
#define EX_DATA_UACCESS_WRITE BIT(0)
29+
2630
#ifdef __ASSEMBLY__
2731

2832
#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
@@ -69,6 +73,10 @@
6973
.endif
7074
.endm
7175

76+
.macro _asm_extable_uaccess_cpy, insn, fixup, uaccess_is_write
77+
__ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_UACCESS_CPY, \uaccess_is_write)
78+
.endm
79+
7280
#else /* __ASSEMBLY__ */
7381

7482
#include <linux/stringify.h>

arch/arm64/include/asm/extable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,5 @@ bool ex_handler_bpf(const struct exception_table_entry *ex,
4545
}
4646
#endif /* !CONFIG_BPF_JIT */
4747

48-
bool fixup_exception(struct pt_regs *regs);
48+
bool fixup_exception(struct pt_regs *regs, unsigned long esr);
4949
#endif

arch/arm64/mm/extable.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@
88
#include <linux/uaccess.h>
99

1010
#include <asm/asm-extable.h>
11+
#include <asm/esr.h>
1112
#include <asm/ptrace.h>
1213

14+
static bool cpy_faulted_on_uaccess(const struct exception_table_entry *ex,
15+
unsigned long esr)
16+
{
17+
bool uaccess_is_write = FIELD_GET(EX_DATA_UACCESS_WRITE, ex->data);
18+
bool fault_on_write = esr & ESR_ELx_WNR;
19+
20+
return uaccess_is_write == fault_on_write;
21+
}
22+
1323
static inline unsigned long
1424
get_ex_fixup(const struct exception_table_entry *ex)
1525
{
@@ -29,6 +39,17 @@ static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
2939
return true;
3040
}
3141

42+
static bool ex_handler_uaccess_cpy(const struct exception_table_entry *ex,
43+
struct pt_regs *regs, unsigned long esr)
44+
{
45+
/* Do not fix up faults on kernel memory accesses */
46+
if (!cpy_faulted_on_uaccess(ex, esr))
47+
return false;
48+
49+
regs->pc = get_ex_fixup(ex);
50+
return true;
51+
}
52+
3253
static bool
3354
ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
3455
struct pt_regs *regs)
@@ -56,7 +77,7 @@ ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
5677
return true;
5778
}
5879

59-
bool fixup_exception(struct pt_regs *regs)
80+
bool fixup_exception(struct pt_regs *regs, unsigned long esr)
6081
{
6182
const struct exception_table_entry *ex;
6283

@@ -70,6 +91,8 @@ bool fixup_exception(struct pt_regs *regs)
7091
case EX_TYPE_UACCESS_ERR_ZERO:
7192
case EX_TYPE_KACCESS_ERR_ZERO:
7293
return ex_handler_uaccess_err_zero(ex, regs);
94+
case EX_TYPE_UACCESS_CPY:
95+
return ex_handler_uaccess_cpy(ex, regs, esr);
7396
case EX_TYPE_LOAD_UNALIGNED_ZEROPAD:
7497
return ex_handler_load_unaligned_zeropad(ex, regs);
7598
}

arch/arm64/mm/fault.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
375375
* Are we prepared to handle this kernel fault?
376376
* We are almost certainly not prepared to handle instruction faults.
377377
*/
378-
if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
378+
if (!is_el1_instruction_abort(esr) && fixup_exception(regs, esr))
379379
return;
380380

381381
if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs),

0 commit comments

Comments
 (0)