diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 1fbab854a51b0ee5872b9f23991c3f0ae72fb9b3..5f1161be1a83ff107d4522b97966f3d9a11c3c60 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -47,8 +47,13 @@ struct thread_info { #endif }; +#ifdef CONFIG_ARM64_PTR_AUTH #define thread_saved_pc(tsk) \ - ((unsigned long)(tsk->thread.cpu_context.pc)) + ptrauth_strip_insn_pac((unsigned long)(tsk->thread.cpu_context.pc)) +#else +#define thread_saved_pc(tsk) \ + ((unsigned long)(tsk->thread.cpu_context.pc)) +#endif #define thread_saved_sp(tsk) \ ((unsigned long)(tsk->thread.cpu_context.sp)) #define thread_saved_fp(tsk) \ diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c index c56cec242274e9e498489e537d4f0e673e4ffe1e..11bb5bf9e2e0fa4b43ee49cd4ce62ed32ebebdd9 100644 --- a/arch/arm64/kernel/alternative.c +++ b/arch/arm64/kernel/alternative.c @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif + #define __ALT_PTR(a,f) ((void *)&(a)->f + (a)->f) #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset) #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset) @@ -164,9 +168,13 @@ static void __nocfi __apply_alternatives(void *alt_region, bool is_module, if (alt->cpufeature < ARM64_CB_PATCH) alt_cb = patch_alternative; - else + else { alt_cb = ALT_REPL_PTR(alt); - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + alt_cb = pauth_pacia(alt_cb, __builtin_get_modifier_bytype(alternative_cb_t)); +#endif + } + alt_cb(alt, origptr, updptr, nr_inst); if (!is_module) { diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 34ef70877de45abb1e2e9d9a93ce7e54b41df08d..df955f1d637ffb85aa0039a11bd09e75972fa229 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -23,6 +23,7 @@ #include #include #include +#include int main(void) { @@ -144,6 +145,10 @@ int main(void) DEFINE(PTRAUTH_USER_KEY_APDB, offsetof(struct ptrauth_keys_user, apdb)); DEFINE(PTRAUTH_USER_KEY_APGA, offsetof(struct ptrauth_keys_user, apga)); DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia)); +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + DEFINE(GIC_HANDLE_IRQ_TYPEID, __builtin_get_modifier_bytype(void (*)(struct pt_regs *))); + DEFINE(KERNEL_INIT_TYPEID, __builtin_get_modifier_bytype(int (*)(void *))); +#endif BLANK(); #endif return 0; diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index d5bc1dbdd2fda84cd1e6e9508c07be5b41fae793..9751536802c63c70710c1177723b6e1da8854a88 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -482,7 +482,12 @@ tsk .req x28 // current thread_info ldr_l x1, \handler mov x0, sp irq_stack_entry +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + mov x16, GIC_HANDLE_IRQ_TYPEID + blraa x1, x16 +#else blr x1 +#endif irq_stack_exit .endm @@ -1037,7 +1042,12 @@ SYM_CODE_START(ret_from_fork) bl schedule_tail cbz x19, 1f // not a kernel thread mov x0, x20 +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + mov x16, KERNEL_INIT_TYPEID + blraa x19, x16 +#else blr x19 +#endif 1: get_current_task tsk b ret_to_user SYM_CODE_END(ret_from_fork) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index e1c25fa3b8e6ca6566876ece29871cefdcd73d1b..6e8f91030c130477461ec08b095841c56ccee717 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -462,6 +462,9 @@ SYM_FUNC_START_LOCAL(__primary_switched) ldp x29, x30, [sp], #16 // we must enable KASLR, return ret // to __primary_switch() 0: +#endif +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + bl ptrauth_init_globals #endif add sp, sp, #16 mov x29, #0 diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 22275d8518eb39fa8bd4287deaad832453cfa0fb..b2bf38f29fc5b853ad8294128d0c3767b7cbd8c7 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -436,7 +436,14 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, p->thread.cpu_context.x19 = stack_start; p->thread.cpu_context.x20 = stk_sz; } + // when CONFIG_ARM64_PTR_AUTH_FWD_CFI is true, directly assignment will use a modifier(function type) to sign pc + // which is used ret to jump in cpu_switch_to +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + asm ("mov %0, %1\n" : "=&r" (p->thread.cpu_context.pc) : "r" (ret_from_fork)); +#else p->thread.cpu_context.pc = (unsigned long)ret_from_fork; +#endif + p->thread.cpu_context.sp = (unsigned long)childregs; ptrace_hw_copy_thread(p); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 795d224f184ff2ce63d8427f5e70d4a9a89fd4ef..d95946c075c2680fa77b5bbcb7d6ea496bee6ff8 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -39,6 +39,8 @@ #include #include +#include + struct fault_info { int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); @@ -307,7 +309,13 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, */ if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) return; - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI_DEBUG + if (is_el1_instruction_abort(esr) && ((addr >> 48) ^ 0xffff)) { + regs->pc = ptrauth_strip_insn_pac(addr); + printk(KERN_ERR "pac-blraa exception PC = %llx X30 = %lx\n", regs->pc, regs->regs[30]); + return; + } +#endif if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs), "Ignoring spurious kernel translation fault at virtual address %016lx\n", addr)) return; diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index ed600473ad7e3e63d4d27a7e634bb96dc59320fa..2f74322bc335f244eb0ff6d2130ea1c523a39cf1 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -23,6 +23,9 @@ #include #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif #include "tpm.h" DEFINE_IDR(dev_nums_idr); @@ -389,10 +392,16 @@ struct tpm_chip *tpmm_chip_alloc(struct device *pdev, chip = tpm_chip_alloc(pdev, ops); if (IS_ERR(chip)) return chip; - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + rc = devm_add_action_or_reset(pdev, + pauth_sign_ptr_parameter(put_device, + __builtin_get_modifier_bytype(void (*)(void *)), a), + &chip->dev); +#else rc = devm_add_action_or_reset(pdev, (void (*)(void *)) put_device, &chip->dev); +#endif if (rc) return ERR_PTR(rc); diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile index 0d768a13e2bb705ff645df6cf1e3d1c7a0055726..057aeb94cbba4bae7cce8875395becf3daa8b6c0 100644 --- a/drivers/misc/lkdtm/Makefile +++ b/drivers/misc/lkdtm/Makefile @@ -10,6 +10,7 @@ lkdtm-$(CONFIG_LKDTM) += rodata_objcopy.o lkdtm-$(CONFIG_LKDTM) += usercopy.o lkdtm-$(CONFIG_LKDTM) += stackleak.o lkdtm-$(CONFIG_LKDTM) += cfi.o +lkdtm-$(CONFIG_LKDTM) += ptrauth_ext.o KASAN_SANITIZE_stackleak.o := n KCOV_INSTRUMENT_rodata.o := n diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index 32b3d77368e37d734ad541e1cda80997fa733345..193791da61a64e80f34d4722a75082e580890e81 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -174,6 +174,10 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(STACKLEAK_ERASING), CRASHTYPE(CFI_FORWARD_PROTO), CRASHTYPE(DOUBLE_FAULT), + CRASHTYPE(CFI_FWD_CHANGE_FUN_TYPE), + CRASHTYPE(CFI_FWD_CMPXCHG), + CRASHTYPE(CFI_FWD_AUT_PTR), + CRASHTYPE(CFI_FWD_ADD_INSN), }; diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index 6dec4c9b442ff34e9c516e54ee8d4706af7ad0bd..fd5614643f5294ed946b4556836817a283f1338e 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -101,5 +101,11 @@ void lkdtm_STACKLEAK_ERASING(void); /* cfi.c */ void lkdtm_CFI_FORWARD_PROTO(void); +void lkdtm_CFI_FWD_CHANGE_FUN_TYPE(void); +void lkdtm_CFI_FWD_CMPXCHG(void); +void lkdtm_CFI_FWD_AUT_PTR(void); +void lkdtm_CFI_FWD_ADD_INSN(void); + + #endif diff --git a/drivers/misc/lkdtm/ptrauth_ext.c b/drivers/misc/lkdtm/ptrauth_ext.c new file mode 100644 index 0000000000000000000000000000000000000000..ed78282e371855f3947b189e6eb9f56466ca4341 --- /dev/null +++ b/drivers/misc/lkdtm/ptrauth_ext.c @@ -0,0 +1,178 @@ +#ifdef CONFIG_ARM64_PTR_AUTH_EXT +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + +#include +#include +#include "lkdtm.h" + +typedef void (*void_fun_pointer)(void); + +struct test_struct { + void_fun_pointer fun; + void *vptr; + unsigned long ulptr; +}; + +static struct test_struct data = { + .fun = NULL, + .vptr = NULL, + .ulptr = 0L, +}; + +static noinline void fun_symbol(void) +{ + printk("this is PAC front cfi test, 1"); +} + +static noinline int fun_symbol_2(void) +{ + printk("this is PAC front cfi test, 2"); + return (unsigned long)data.fun >> 48; +} + +static noinline int fun_symbol_3(void) +{ + printk("this is PAC front cfi test, 3"); + return (unsigned long)data.fun >> 48; +} + +static noinline void store_fun_pointer(void_fun_pointer fun, int val) +{ + if (val == 0) { + data.fun = fun; + } + + if (val == 1) { + data.vptr = fun; + } + + if (val == 2) { + data.ulptr = (unsigned long)fun; + } +} + +static noinline void store_pointer(void *fun, int val) +{ + if (val == 0) { + data.fun = fun; + } + + if (val == 1) { + data.vptr = fun; + } + + if (val == 2) { + data.ulptr = (unsigned long)fun; + } +} + +static noinline void use_fun_pointer(int val) +{ + if (val == 0) { + data.fun(); + } + + if (val == 1) { + void_fun_pointer ptr = data.vptr; + ptr(); + } + + if (val == 2) { + void_fun_pointer ptr = (void_fun_pointer)data.ulptr; + ptr(); + } +} + +typedef void chg_func(void); +static chg_func *chg_test_fun; + +static noinline int fwd_cmpxchg(chg_func *cmp_fn) +{ + uintptr_t fn_data; + int ret = 0; + + ret = (cmpxchg((chg_func **)&chg_test_fun, cmp_fn, NULL) == cmp_fn) ? 0 : -1; + if (ret == -1) { + printk("because of resigned, cmpxchg failed\n"); + } + + fn_data = (uintptr_t)cmp_fn; + ret = ((uintptr_t)cmpxchg((chg_func **)&chg_test_fun, cmp_fn, NULL) == fn_data) ? 0 : -1; + if (ret == 0) { + printk("we avoid resigning !!!\n"); + } + return ret; +} + +static noinline u64 fun_base(void) +{ + return 0; +} + +void lkdtm_CFI_FWD_CHANGE_FUN_TYPE(void) +{ + store_fun_pointer(fun_symbol, 0); + use_fun_pointer(0); + //作非匹配类型的函数指针入参 + store_fun_pointer(pauth_sign_ptr_parameter(fun_symbol_2, \ + __builtin_get_modifier_bytype(void_fun_pointer), a), 0); + use_fun_pointer(0); + // 作非匹配类型的void *入参 + store_pointer(pauth_sign_ptr_parameter(fun_symbol_3, + __builtin_get_modifier_bytype(void_fun_pointer), a), 0); + use_fun_pointer(0); + printk("welcome here, everything is ok !!!\n"); +} + +void lkdtm_CFI_FWD_CMPXCHG(void) +{ + int ret = 0; + ret = fwd_cmpxchg(chg_test_fun); + if (ret == -1) { + printk("cmpxchg is failed !\n"); + } +} + +void lkdtm_CFI_FWD_AUT_PTR(void) +{ + unsigned long temp_ulptr; + if (chg_test_fun == NULL) { + chg_test_fun = fun_symbol; + } + printk("this is the ptr before aut, %llx\n", chg_test_fun); + temp_ulptr = (unsigned long)pauth_autia(chg_test_fun, + __builtin_get_modifier_bytype(chg_test_fun)); + if (temp_ulptr >> 48 ^0xffff) { + printk("aut failed\n"); + } + printk("this is the ptr after aut, %llx\n", temp_ulptr); +} + +void lkdtm_CFI_FWD_ADD_INSN(void) +{ + typedef u64 (*target_fn_t)(u64); + u32 num; + unsigned long temp_ulptr; + target_fn_t call_pac; + uintptr_t addr; + + num = get_random_int(); + printk("this is insn, %d/n", num); + + addr = (uintptr_t)fun_base + (s32)(num); + printk("this is the address which need to be paced, %llx\n", addr); + + call_pac = + (target_fn_t)(pauth_pacia((void *)addr, __builtin_get_modifier_bytype(target_fn_t))); + printk("this is the address has been paced, %llx\n", call_pac); + + temp_ulptr = (unsigned long)pauth_autia(call_pac, + __builtin_get_modifier_bytype(target_fn_t)); + if (temp_ulptr >> 48 ^0xffff) { + printk("aut failed\n"); + } + printk("this is the address after aut, %llx\n", temp_ulptr); +} + +#endif +#endif diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c index 1913dc2c8fa0864d6d266842a18f68f220a69214..7ae113fef4cd6e7c6e46cfffaaf6b52f092dbd5a 100644 --- a/drivers/pci/controller/dwc/pci-meson.c +++ b/drivers/pci/controller/dwc/pci-meson.c @@ -18,6 +18,9 @@ #include #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif #include "pcie-designware.h" @@ -187,9 +190,16 @@ static inline struct clk *meson_pcie_probe_clock(struct device *dev, return ERR_PTR(ret); } +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI devm_add_action_or_reset(dev, - (void (*) (void *))clk_disable_unprepare, - clk); + pauth_sign_ptr_parameter(clk_disable_unprepare, + __builtin_get_modifier_bytype(void (*)(void *)), a), + clk); +#else + devm_add_action_or_reset(dev, + (void (*) (void *))clk_disable_unprepare, + clk); +#endif return clk; } diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index 91b7359b79a2ff8bbf6327c86c1510278adf0e02..9b20f89196f715d7ea907809ec94549afbb58066 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif /* Register offsets */ #define AML_UART_WFIFO 0x00 @@ -673,11 +676,16 @@ static inline struct clk *meson_uart_probe_clock(struct device *dev, dev_err(dev, "couldn't enable clk\n"); return ERR_PTR(ret); } - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + devm_add_action_or_reset(dev, + pauth_sign_ptr_parameter(clk_disable_unprepare, + __builtin_get_modifier_bytype(void (*)(void *)), a), + clk); +#else devm_add_action_or_reset(dev, (void(*)(void *))clk_disable_unprepare, clk); - +#endif return clk; } diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h index e9304c95ceea2a0898d797a2e522219d2e0ef3dc..eabc012e3b21fcd0e590c462c1920dfa2b24c483 100644 --- a/include/uapi/asm-generic/signal-defs.h +++ b/include/uapi/asm-generic/signal-defs.h @@ -19,7 +19,12 @@ typedef void __signalfn_t(int); typedef __signalfn_t __user *__sighandler_t; typedef void __restorefn_t(void); + +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +typedef void __user *__sigrestore_t; +#else typedef __restorefn_t __user *__sigrestore_t; +#endif #define SIG_DFL ((__force __sighandler_t)0) /* default signal handling */ #define SIG_IGN ((__force __sighandler_t)1) /* ignore signal */ diff --git a/init/main.c b/init/main.c index 30d6afeae93272fd1f8608c5e339df2eabef89f9..665d0f113187abb1a4785439c89d4269077c37b6 100644 --- a/init/main.c +++ b/init/main.c @@ -102,6 +102,10 @@ #include #endif +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif + #include #include #include @@ -1064,7 +1068,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) prevent_tail_call_optimization(); } - +#ifndef CONFIG_ARM64_PTR_AUTH_FWD_CFI /* Call all constructor functions linked into the kernel. */ static void __init do_ctors(void) { @@ -1075,6 +1079,7 @@ static void __init do_ctors(void) (*fn)(); #endif } +#endif #ifdef CONFIG_KALLSYMS struct blacklist_entry { @@ -1120,8 +1125,12 @@ static bool __init_or_module initcall_blacklisted(initcall_t fn) if (list_empty(&blacklisted_initcalls)) return false; - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + addr = (unsigned long)pauth_autia(dereference_function_descriptor(fn), + __builtin_get_modifier_bytype(initcall_t)); +#else addr = (unsigned long) dereference_function_descriptor(fn); +#endif sprint_symbol_no_offset(fn_name, addr); /* @@ -1323,7 +1332,9 @@ static void __init do_basic_setup(void) cpuset_init_smp(); driver_init(); init_irq_proc(); +#ifndef CONFIG_ARM64_PTR_AUTH_FWD_CFI do_ctors(); +#endif usermodehelper_enable(); do_initcalls(); } diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index fd2aa6b9909eca3eb76ff81c65f37fdd98ca2a67..8eecc56e582915c002b269a8971ecf6b3073a656 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -36,6 +36,10 @@ #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif + /* Registers */ #define BPF_R0 regs[BPF_REG_0] #define BPF_R1 regs[BPF_REG_1] @@ -1550,16 +1554,46 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack) * preserves BPF_R6-BPF_R9, and stores return value * into BPF_R0. */ +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + { + typedef u64 (*target_fn_t)(u64, u64, u64, u64, u64); + target_fn_t call_pac; + uintptr_t addr; + addr = (uintptr_t)__bpf_call_base + (s32)(insn->imm); + call_pac = + (target_fn_t)(pauth_pacia((void *)addr, __builtin_get_modifier_bytype(target_fn_t))); + BPF_R0 = call_pac(BPF_R1, BPF_R2, BPF_R3, + BPF_R4, BPF_R5); + CONT; + } +#else BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3, BPF_R4, BPF_R5); CONT; +#endif JMP_CALL_ARGS: +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + { + typedef u64 (*target_fn_t)(u64, u64, u64, u64, u64, const struct bpf_insn *); + target_fn_t call_pac; + uintptr_t addr; + addr = (uintptr_t)__bpf_call_base + (s32)(insn->imm); + call_pac = + (target_fn_t)(pauth_pacia((void *)addr, __builtin_get_modifier_bytype(target_fn_t))); + BPF_R0 = call_pac(BPF_R1, BPF_R2, + BPF_R3, BPF_R4, + BPF_R5, + insn + insn->off + 1); + CONT; + } +#else BPF_R0 = (__bpf_call_base_args + insn->imm)(BPF_R1, BPF_R2, BPF_R3, BPF_R4, BPF_R5, insn + insn->off + 1); CONT; +#endif JMP_TAIL_CALL: { struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2; diff --git a/kernel/events/core.c b/kernel/events/core.c index e9b354d521a3811d70542ac81793a60bcf1200e2..913c6455bfe3eb0b0460cb42d110af680d072706 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -52,6 +52,10 @@ #include #include +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif + #include "internal.h" #include @@ -10771,9 +10775,15 @@ perf_event_mux_interval_ms_store(struct device *dev, struct perf_cpu_context *cpuctx; cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + cpu_function_call(cpu, + pauth_sign_ptr_parameter(perf_mux_hrtimer_restart, \ + __builtin_get_modifier_bytype(remote_function_f), a), + cpuctx); +#else cpu_function_call(cpu, (remote_function_f)perf_mux_hrtimer_restart, cpuctx); +#endif } cpus_read_unlock(); mutex_unlock(&mux_interval_mutex); diff --git a/kernel/module.c b/kernel/module.c index a8f341a49a01eb44a5e57756a835577b1a444483..d91a53714086de48a0c0b9dd4719baa4596a70ed 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -60,6 +60,10 @@ #include #include "module-internal.h" +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI +#include +#endif + #define CREATE_TRACE_POINTS #include @@ -3679,8 +3683,21 @@ static void do_mod_ctors(struct module *mod) unsigned long i; for (i = 0; i < mod->num_ctors; i++) +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + { + ctor_fn_t cfn = mod->ctors[i]; + asm volatile("blr %0" : : "r" (cfn)); + } + if (mod->init) { + mod->init = pauth_pacia(mod->init, __builtin_get_modifier_bytype(mod->init)); + } + if (mod->exit) { + mod->exit = pauth_pacia(mod->exit, __builtin_get_modifier_bytype(mod->exit)); + } +#else mod->ctors[i](); #endif +#endif } /* For freeing module_init on success, in case kallsyms traversing */ diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c index 9e3574880cb03e8da64fc7169db5f76ff857446f..5b9e8f02a6f7696fa13deeaa446b6e10a22e5860 100644 --- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -23,9 +23,14 @@ EXPORT_SYMBOL(inet6_register_icmp_sender); int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) { int ret; - +#ifdef CONFIG_ARM64_PTR_AUTH_FWD_CFI + uintptr_t fn_data = (uintptr_t)fn; + ret = ((uintptr_t)cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn_data) ? + 0 : -EINVAL; +#else ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ? 0 : -EINVAL; +#endif synchronize_net();