Hi Jarkko,

On Wed, Jul 1, 2026 at 3:50 PM Jarkko Sakkinen <[email protected]> wrote:
>
> On Wed, Jul 01, 2026 at 02:57:33PM +1200, Tao Liu wrote:
> > A NULL pointer dereference issue is noticed in riscv's 
> > machine_kexec_prepare,
> > where image->segment[i].buf might be NULL and copied unchecked.
> >
> > The NULL buf comes from security/integrity/ima/ima_kexec.c:
> > ima_add_kexec_buffer(), where kbuf is added by kexec_add_buffer(),
> > but kbuf.buffer is NULL
>
> This should have a proper call sequence. Now the root cause is
> obfuscated.

Sure, I will attach the stack trace in v4. Here is the one:

[   62.867540] kexec_file(Image): Loaded kernel at 0x80200000
bufsz=0x34ed800 memsz=0x35d0000
[   62.879983] Unable to handle kernel access to user memory without
uaccess routines at virtual address 0000000000000000
[   62.880736] Current kexec pgtable: 4K pagesize, 57-bit VAs,
pgdp=0x00000001062eb000
[   62.881185] [0000000000000000] pgd=00000000413b4401,
p4d=000000004151bc01, pud=00000000415b7801, pmd=0000000040af5801,
pte=0000000000000000
[   62.881969] Oops [#1]
[   62.882077] Modules linked in:
[   62.882717] CPU: 1 UID: 0 PID: 894 Comm: kexec Not tainted 7.1.1 #4
PREEMPT(lazy)
[   62.883037] Hardware name: QEMU QEMU Virtual Machine, BIOS
edk2-20260508-2.fc44 05/08/2026
[   62.883365] epc : __memcpy+0xd4/0xf8
[   62.883685]  ra : machine_kexec_prepare+0x8a/0x298
[   62.883914] epc : ffffffff81393ee8 ra : ffffffff800366ca sp :
ff20000004a83d10
[   62.884214]  gp : ffffffff83258db8 tp : ff6000008573db80 t0 :
ffffffff80033640
[   62.884433]  t1 : 2152ffffffffffc0 t2 : 0000000003000000 s0 :
ff20000004a83d80
[   62.884710]  s1 : 0000000000000000 a0 : ff20000004a83d10 a1 :
0000000000000000
[   62.884987]  a2 : 0000000000000028 a3 : 0000000000000028 a4 :
0000000000000000
[   62.885208]  a5 : 0000000000000000 a6 : 0000000104e33fff a7 :
0000000000000000
[   62.885486]  s2 : ff60000082a35800 s3 : 0000000000000000 s4 :
0000000000000010
[   62.885774]  s5 : 0000000000000028 s6 : ff20000004a83d10 s7 :
0000000000000005
[   62.886005]  s8 : 00000000000000c0 s9 : 000000000ac0d220 s10:
ffffffff835420e8
[   62.886218]  s11: 0000000000000000 t3 : ffffff800000007c t4 :
ff1c000002138d00
[   62.886515]  t5 : ffffffffffffffff t6 : ff20000004a83d10 ssp :
0000000000000000
[   62.886860] status: 0000000200000120 badaddr: 0000000000000000
cause: 000000000000000d
[   62.887162] [<ffffffff81393ee8>] __memcpy+0xd4/0xf8
[   62.887388] [<ffffffff801b253a>] __do_sys_kexec_file_load+0x1b2/0x338
[   62.887612] [<ffffffff801b26e4>] __riscv_sys_kexec_file_load+0x24/0x40
[   62.887855] [<ffffffff81395ea4>] do_trap_ecall_u+0x1a4/0x5a8
[   62.888134] [<ffffffff813a9eec>] handle_exception+0x16c/0x178
[   62.888445] Code: 7613 07f6 ca05 86b3 00c5 e7b3 01f5 8fd5 8b8d eb89
(4198) 0591
[   62.889223] ---[ end trace 0000000000000000 ]---
Segmentation fault         kexec -l /boot/vmlinuz-7.1.1
--initrd=/boot/initramfs-7.1.1.img --reuse-cmdline

(gdb) p image->segment[0]
$3 = {{buf = 0x0, kbuf = 0x0}, bufsz = 0, mem = 10737586176, memsz = 4096}

The buf = 0x0 and bufsz = 0 comes from ima_add_kexec_buffer(), thought
I'm not sure why it added a NULL segment, but it is no harm to add a
NULL checker here in case any other scenarios similar as IMA.

>
> >
> > Fix this by simply adding a check before copy.
> >
> > Fixes: b7fb4d78a6ad ("RISC-V: use memcpy for kexec_file mode")
> > Acked-by: Baoquan He <[email protected]>
> > Acked-by: Pratyush Yadav <[email protected]>
> > Signed-off-by: Tao Liu <[email protected]>
> > ---
> >
> > v3 -> v2: Add fixes tag; Replace "reference" to "dereference".
> > link to v2: 
> > https://lore.kernel.org/linux-riscv/[email protected]/
> > link to v1: 
> > https://lore.kernel.org/linux-riscv/[email protected]/
> >
> > ---
> >  arch/riscv/kernel/machine_kexec.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/riscv/kernel/machine_kexec.c 
> > b/arch/riscv/kernel/machine_kexec.c
> > index 2306ce3e5f22..afc68f6a4aa1 100644
> > --- a/arch/riscv/kernel/machine_kexec.c
> > +++ b/arch/riscv/kernel/machine_kexec.c
> > @@ -41,6 +41,13 @@ machine_kexec_prepare(struct kimage *image)
> >               if (image->segment[i].memsz <= sizeof(fdt))
> >                       continue;
> >
> > +             /*
> > +              * Some segments (e.g. IMA) reserve space but have no buffer
> > +              * loaded yet. Skip them as they cannot contain an FDT.
> > +              */
>
> This is destined to rot over time. It also adds up also potentially to
> the backporting effort while backporting to stable kernes. And most
> importantly. Please, don't document every other null check.

OK, will get rid of it.

Thanks,
Tao Liu

>
> > +             if (image->segment[i].buf == NULL)
>
> if (!image->segments[i].buf)
>
> > +                     continue;
> > +
> >               if (image->file_mode)
> >                       memcpy(&fdt, image->segment[i].buf, sizeof(fdt));
> >               else if (copy_from_user(&fdt, image->segment[i].buf, 
> > sizeof(fdt)))
> > --
> > 2.54.0
> >
> >
>
> BR, Jarkko
>


Reply via email to