Re: [PATCH 0/8] unwind, arm64: add sframe unwinder for kernel

Weinan Liu <[email protected]>
Newsgroups org.kernel.vger.linux-toolchains,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-kernel,org.kernel.vger.live-patching
Message-ID <[email protected]>
> After some debugging this is what I found:
> 
> devtmpfsd() calls devtmpfs_work_loop() which is marked '__noreturn' and has an
> infinite loop. The compiler puts the `bl` to devtmpfs_work_loop() as the the
> last instruction in devtmpfsd() and therefore on entry to devtmpfs_work_loop(),
> LR points to an instruction beyond devtmpfsd() and this consfuses the unwinder.
> 
> ffff800080d9a070 <devtmpfsd>:
> ffff800080d9a070:       d503201f        nop
> ffff800080d9a074:       d503201f        nop
> ffff800080d9a078:       d503233f        paciasp
> ffff800080d9a07c:       a9be7bfd        stp     x29, x30, [sp, #-32]!
> ffff800080d9a080:       910003fd        mov     x29, sp
> ffff800080d9a084:       f9000bf3        str     x19, [sp, #16]
> ffff800080d9a088:       943378e8        bl      ffff800081a78428 <devtmpfs_setup>
> ffff800080d9a08c:       90006ca1        adrp    x1, ffff800081b2e000 <unique_processor_ids+0x3758>
> ffff800080d9a090:       2a0003f3        mov     w19, w0
> ffff800080d9a094:       912de021        add     x1, x1, #0xb78
> ffff800080d9a098:       91002020        add     x0, x1, #0x8
> ffff800080d9a09c:       97cd2a43        bl      ffff8000800e49a8 <complete>
> ffff800080d9a0a0:       340000d3        cbz     w19, ffff800080d9a0b8 <devtmpfsd+0x48>
> ffff800080d9a0a4:       2a1303e0        mov     w0, w19
> ffff800080d9a0a8:       f9400bf3        ldr     x19, [sp, #16]
> ffff800080d9a0ac:       a8c27bfd        ldp     x29, x30, [sp], #32
> ffff800080d9a0b0:       d50323bf        autiasp
> ffff800080d9a0b4:       d65f03c0        ret
> ffff800080d9a0b8:       97f06526        bl      ffff8000809b3550 <devtmpfs_work_loop>
> ffff800080d9a0bc:       00000000        udf     #0
> ffff800080d9a0c0:       d503201f        nop
> ffff800080d9a0c4:       d503201f        nop
> 
> find_fde() got pc=0xffff800080d9a0bc which is not in [sfde_func_start_address, sfde_func_size)
> 
> output for readelf --sframe for devtmpfsd()
> 
> func idx [51825]: pc = 0xffff800080d9a070, size = 76 bytes
>     STARTPC           CFA       FP        RA
>     ffff800080d9a070  sp+0      u         u
>     ffff800080d9a07c  sp+0      u         u[s]
>     ffff800080d9a080  sp+32     c-32      c-24[s]
>     ffff800080d9a0b0  sp+0      u         u[s]
>     ffff800080d9a0b4  sp+0      u         u
>     ffff800080d9a0b8  sp+32     c-32      c-24[s]
> 
> The unwinder and all the related infra is assuming that the return address
> will be part of a valid function which is not the case here.
> 
> I am not sure which component needs to be fixed here, but the following
> patch(which is a hack) fixes the issue by considering the return address as
> part of the function descriptor entry.
> 
> -- 8< --
> 
> diff --git a/kernel/sframe_lookup.c b/kernel/sframe_lookup.c
> index 846f1da95..28bec5064 100644
> --- a/kernel/sframe_lookup.c
> +++ b/kernel/sframe_lookup.c
> @@ -82,7 +82,7 @@ static struct sframe_fde *find_fde(const struct sframe_table *tbl, unsigned long
>         if (f >= tbl->sfhdr_p->num_fdes || f < 0)
>                 return NULL;
>         fdep = tbl->fde_p + f;
> -       if (ip < fdep->start_addr || ip >= fdep->start_addr + fdep->size)
> +       if (ip < fdep->start_addr || ip > fdep->start_addr + fdep->size)
>                 return NULL;
> 
>         return fdep;
> @@ -106,7 +106,7 @@ static int find_fre(const struct sframe_table *tbl, unsigned long pc,
>         else
>                 ip_off = (int32_t)(pc - (unsigned long)tbl->sfhdr_p) - fdep->start_addr;
> 
> -       if (ip_off < 0 || ip_off >= fdep->size)
> +       if (ip_off < 0 || ip_off > fdep->size)
>                 return -EINVAL;
> 
>         /*
> 
> -- >8 --
> 
> Thanks,
> Puranjay

Thank you for reporting this issue.
I just found out that Josh also intentionally uses '>' instead of '>=' for the same reason
https://lore.kernel.org/lkml/20250122225257.h64ftfnorofe7cb4@jpoimboe/T/#m6d70a20ed9f5b3bbe5b24b24b8c5dcc603a79101

QQ, do we need to care the stacktrace after '__noreturn' function?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.