----- 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.kach...@arm.com)

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.kach...@arm.com)

> +                     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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to