Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions kernel/patch/common/secpass.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include <uapi/asm-generic/errno.h>

#include <predata.h>
#ifndef CONFIG_X86_64
#include <asm/ptrace.h>
#endif

struct pt_regs;
int cfi_bypass = 0;
Expand All @@ -18,6 +21,22 @@ static inline bool should_cfi_pass(unsigned long target)
return is_kp_text_area(target) || is_kp_hook_area(target) || is_kpm_rox_area(target);
}

#ifndef CONFIG_X86_64
static void (*skip_cfi_brk)(struct pt_regs *, unsigned long);

/* LTO can inline report_cfi_failure into the arm64 trap handler. Preserve
* the existing KP/KPM-only exception even when that function hook is bypassed. */
static void before_cfi_handler(hook_fargs2_t *args, void *udata)
{
struct pt_regs *regs = (struct pt_regs *)args->arg0;
unsigned int target_reg = args->arg1 & 0x1f; /* CFI_BRK_IMM_TARGET */
if (user_mode(regs) || target_reg == 31 || !should_cfi_pass(regs->regs[target_reg])) return;
skip_cfi_brk(regs, 4);
args->ret = 0; /* DBG_HOOK_HANDLED */
args->skip_origin = 1;
}
#endif

enum bug_trap_type
{
BUG_TRAP_TYPE_NONE = 0,
Expand Down Expand Up @@ -50,6 +69,16 @@ int bypass_kcfi()
{
int rc = 0;

#ifndef CONFIG_X86_64
unsigned long cfi_handler_addr = kallsyms_lookup_name("cfi_handler");
skip_cfi_brk = (typeof(skip_cfi_brk))kallsyms_lookup_name("arm64_skip_faulting_instruction");
if (cfi_handler_addr && skip_cfi_brk) {
rc = hook_wrap2((void *)cfi_handler_addr, before_cfi_handler, 0, 0);
log_boot("hook cfi_handler: %llx, rc: %d\n", cfi_handler_addr, rc);
if (rc) goto out;
}
#endif

// 6.1.0
// todo: Is there more elegant way?
unsigned long report_cfi_failure_addr = patch_config->report_cfi_failure;
Expand Down