----- Original Message ----- > Pointer authentication support is added in the recent versions of the arm64 > kernel. This basically add PAC bits to the top unused bits of the lr > register in the stack to prevent ROP kind of attack. > > However the presence of PAC bits fails to match with the correct symbol > name. Hence a KERNELPACMASK field is added in the vmcoreinfo to help > in masking out this PAC details. > > This patch fetches the KERNELPACMASK info and use it to mask the PAC bits > and generate correct backtrace and symbol name. > (amit.kachhap@xxxxxxx) Queued for crash-7.2.9: https://github.com/crash-utility/crash/commit/41d61189d60e0fdd6509b96dc8160795263f3229 Thanks, Dave > --- > > Changes sice v2: > * Removed PAC mask check from arm64_is_kernel_exception_frame function > * More details in commit. > > Changes since v1: > * Moved PAC mask code from arm64_print_stackframe_entry to > arm64_unwind_frame. > * PAC mask check on all kernel text during complete stack parsing > with bt -t <pid> command. > * dump_machdep_table now prints CONFIG_ARM64_KERNELPACMASK. > > The kernel version for the corresponding vmcoreinfo entry is posted here[1]. > > [1]: https://lore.kernel.org/patchwork/patch/1211981/ > > > arm64.c | 50 +++++++++++++++++++++++++++++++++++++++++--------- > defs.h | 1 + > 2 files changed, 42 insertions(+), 9 deletions(-) > > diff --git a/arm64.c b/arm64.c > index 7662d71..e0a5cf2 100644 > --- a/arm64.c > +++ b/arm64.c > @@ -84,6 +84,7 @@ static int arm64_get_kvaddr_ranges(struct vaddr_range *); > static void arm64_get_crash_notes(void); > static void arm64_calc_VA_BITS(void); > static int arm64_is_uvaddr(ulong, struct task_context *); > +static void arm64_calc_KERNELPACMASK(void); > > > /* > @@ -213,6 +214,7 @@ arm64_init(int when) > machdep->pagemask = ~((ulonglong)machdep->pageoffset); > > arm64_calc_VA_BITS(); > + arm64_calc_KERNELPACMASK(); > ms = machdep->machspec; > if (ms->VA_BITS_ACTUAL) { > ms->page_offset = ARM64_PAGE_OFFSET_ACTUAL; > @@ -472,6 +474,7 @@ arm64_init(int when) > case LOG_ONLY: > machdep->machspec = &arm64_machine_specific; > arm64_calc_VA_BITS(); > + arm64_calc_KERNELPACMASK(); > arm64_calc_phys_offset(); > machdep->machspec->page_offset = ARM64_PAGE_OFFSET; > break; > @@ -659,6 +662,11 @@ arm64_dump_machdep_table(ulong arg) > fprintf(fp, "%ld\n", ms->VA_BITS_ACTUAL); > else > fprintf(fp, "(unused)\n"); > + fprintf(fp, "CONFIG_ARM64_KERNELPACMASK: "); > + if (ms->CONFIG_ARM64_KERNELPACMASK) > + fprintf(fp, "%lx\n", ms->CONFIG_ARM64_KERNELPACMASK); > + else > + fprintf(fp, "(unused)\n"); > fprintf(fp, " userspace_top: %016lx\n", ms->userspace_top); > fprintf(fp, " page_offset: %016lx\n", ms->page_offset); > fprintf(fp, " vmalloc_start_addr: %016lx\n", ms->vmalloc_start_addr); > @@ -1774,13 +1782,14 @@ static int > arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr) > { > struct arm64_pt_regs *regs; > + struct machine_specific *ms = machdep->machspec; > > regs = (struct arm64_pt_regs > *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(stkptr))]; > > if (INSTACK(regs->sp, bt) && INSTACK(regs->regs[29], bt) && > !(regs->pstate & (0xffffffff00000000ULL | PSR_MODE32_BIT)) && > is_kernel_text(regs->pc) && > - is_kernel_text(regs->regs[30])) { > + is_kernel_text(regs->regs[30] | ms->CONFIG_ARM64_KERNELPACMASK)) { > switch (regs->pstate & PSR_MODE_MASK) > { > case PSR_MODE_EL1t: > @@ -1924,6 +1933,7 @@ arm64_print_stackframe_entry(struct bt_info *bt, int > level, struct arm64_stackfr > * See, for example, "bl schedule" before ret_to_user(). > */ > branch_pc = frame->pc - 4; > + > name = closest_symbol(branch_pc); > name_plus_offset = NULL; > > @@ -2135,7 +2145,7 @@ arm64_unwind_frame(struct bt_info *bt, struct > arm64_stackframe *frame) > unsigned long stack_mask; > unsigned long irq_stack_ptr, orig_sp; > struct arm64_pt_regs *ptregs; > - struct machine_specific *ms; > + struct machine_specific *ms = machdep->machspec; > > stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1; > fp = frame->fp; > @@ -2149,6 +2159,8 @@ arm64_unwind_frame(struct bt_info *bt, struct > arm64_stackframe *frame) > frame->sp = fp + 0x10; > frame->fp = GET_STACK_ULONG(fp); > frame->pc = GET_STACK_ULONG(fp + 8); > + if (is_kernel_text(frame->pc | ms->CONFIG_ARM64_KERNELPACMASK)) > + frame->pc |= ms->CONFIG_ARM64_KERNELPACMASK; > > if ((frame->fp == 0) && (frame->pc == 0)) > return FALSE; > @@ -2200,7 +2212,6 @@ arm64_unwind_frame(struct bt_info *bt, struct > arm64_stackframe *frame) > * irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id()); > * orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on > process stack) > */ > - ms = machdep->machspec; > irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - > 16; > > if (frame->sp == irq_stack_ptr) { > @@ -2802,6 +2813,8 @@ arm64_print_text_symbols(struct bt_info *bt, struct > arm64_stackframe *frame, FIL > char buf2[BUFSIZE]; > char *name; > ulong start; > + ulong val; > + struct machine_specific *ms = machdep->machspec; > > if (bt->flags & BT_TEXT_SYMBOLS_ALL) > start = bt->stackbase; > @@ -2816,8 +2829,10 @@ arm64_print_text_symbols(struct bt_info *bt, struct > arm64_stackframe *frame, FIL > > for (i = (start - bt->stackbase)/sizeof(ulong); i < LONGS_PER_STACK; i++) { > up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); > - if (is_kernel_text(*up)) { > - name = closest_symbol(*up); > + val = *up; > + if (is_kernel_text(val | ms->CONFIG_ARM64_KERNELPACMASK)) { > + val |= ms->CONFIG_ARM64_KERNELPACMASK; > + name = closest_symbol(val); > fprintf(ofp, " %s[%s] %s at %lx", > bt->flags & BT_ERROR_MASK ? > " " : "", > @@ -2826,13 +2841,13 @@ arm64_print_text_symbols(struct bt_info *bt, struct > arm64_stackframe *frame, FIL > MKSTR(bt->stackbase + > (i * sizeof(long)))), > bt->flags & BT_SYMBOL_OFFSET ? > - value_to_symstr(*up, buf2, bt->radix) : > - name, *up); > - if (module_symbol(*up, NULL, &lm, NULL, 0)) > + value_to_symstr(val, buf2, bt->radix) : > + name, val);Prepare for the introduction of ARM64 8.3 Pointer Authentication as in-kernel feature. The value of CONFIG_ARM64_KERNELPACMASK will be exported as a vmcoreinfo entry, and will be used with text return addresses on the kernel stack. (amit.kachhap@xxxxxxx) > + if (module_symbol(val, NULL, &lm, NULL, 0)) > fprintf(ofp, " [%s]", lm->mod_name); > fprintf(ofp, "\n"); > if (BT_REFERENCE_CHECK(bt)) > - arm64_do_bt_reference_check(bt, *up, name); > + arm64_do_bt_reference_check(bt, val, name); > } > } > } > @@ -3135,6 +3150,7 @@ arm64_print_exception_frame(struct bt_info *bt, ulong > pt_regs, int mode, FILE *o > struct syment *sp; > ulong LR, SP, offset; > char buf[BUFSIZE]; > + struct machine_specific *ms = machdep->machspec; > > if (CRASHDEBUG(1)) > fprintf(ofp, "pt_regs: %lx\n", pt_regs); > @@ -3150,6 +3166,8 @@ arm64_print_exception_frame(struct bt_info *bt, ulong > pt_regs, int mode, FILE *o > rows = 4; > } else { > LR = regs->regs[30]; > + if (is_kernel_text (LR | ms->CONFIG_ARM64_KERNELPACMASK)) > + LR |= ms->CONFIG_ARM64_KERNELPACMASK; > SP = regs->sp; > top_reg = 29; > is_64_bit = TRUE; > @@ -4058,6 +4076,20 @@ arm64_swp_offset(ulong pte) > return pte; > } > > +static void arm64_calc_KERNELPACMASK(void) > +{ > + ulong value; > + char *string; > + > + if ((string = pc->read_vmcoreinfo("NUMBER(KERNELPACMASK)"))) { > + value = htol(string, QUIET, NULL); > + free(string); > + machdep->machspec->CONFIG_ARM64_KERNELPACMASK = value; > + if (CRASHDEBUG(1)) > + fprintf(fp, "CONFIG_ARM64_KERNELPACMASK=%lx\n", value); > + } > +} > + > #endif /* ARM64 */ > > > diff --git a/defs.h b/defs.h > index ac24a5d..4c3e509 100644 > --- a/defs.h > +++ b/defs.h > @@ -3263,6 +3263,7 @@ struct machine_specific { > ulong machine_kexec_end; > ulong VA_BITS_ACTUAL; > ulong CONFIG_ARM64_VA_BITS; > + ulong CONFIG_ARM64_KERNELPACMASK; > ulong VA_START; > }; > > -- > 2.17.1 > > -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility