BUG: unable to handle kernel NULL pointer dereference in print_one_line

Status: upstream: reported C repro on 2026/11/04 06:50
Subsystems: trace block
Labels: prio:low
[Documentation on labels]
Reported-by: syzbot+2fca70610179be6c24a4@syzkaller.appspotmail.com
First crash: 4d10h, last: 1d14h
✨ AI-generated root cause summary:

When blktrace events are recorded with version 1 (configured via the BLKTRACESETUP ioctl) while the blk ftrace tracer is enabled, __blk_add_trace() writes events using the v1 struct blk_io_trace layout instead of the v2 struct blk_io_trace2 layout expected by ftrace. In print_one_line(), the entry is unconditionally cast to struct blk_io_trace2, interpreting the process PID (at offset 32 in v1) as the action field (at offset 32 in v2). If this value corresponds to 14 (__BLK_TA_BOUNCE), the bounds check against ARRAY_SIZE(what2act) passes, but what2act[14].print is NULL because __BLK_TA_BOUNCE is an uninitialized entry in what2act[], leading to an instruction fetch at address 0x0 and a kernel panic.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 7649ba73f9e7:

Root Cause Analysis

1. Synopsis and Involved Entities

  • Source File: kernel/trace/blktrace.c
  • Functions: __blk_add_trace(), record_blktrace_event(), record_blktrace_event2(), print_one_line()
  • Structures & Data: struct blk_io_trace (v1 format), struct blk_io_trace2 (v2 format), what2act[] array, enum blktrace_act (include/uapi/linux/blktrace_api.h)

2. Mechanism and Lifecycle Violation

There are two interconnected defects in kernel/trace/blktrace.c that combine to cause this crash:

  1. Format Mismatch in the ftrace Ring Buffer:

    • When tracing is enabled on a block device using the legacy BLKTRACESETUP or BLKTRACESETUP32 ioctls (blk_trace_ioctl() $\to$ blk_trace_setup()), the block trace structure is initialized with bt->version = 1.
    • When the blk tracer is enabled via ftrace (blk_tracer_init(), setting blk_tracer_enabled = true), block I/O operations trigger tracepoint handlers which invoke __blk_add_trace().
    • In __blk_add_trace(), switch (bt->version) contains a case 1: branch (lines 389 and 422) that allocates sizeof(struct blk_io_trace) (48 bytes) and calls record_blktrace_event() (v1 layout) instead of record_blktrace_event2() (v2 layout).
    • However, the ftrace printing pipeline (te_blk_io_trace()) assumes that all TRACE_BLK entries in the ring buffer conform to struct blk_io_trace2 (v2 layout).
    • In struct blk_io_trace (v1), the 32-bit pid is placed at offset 32 and device is placed at offset 36.
    • In struct blk_io_trace2 (v2), the 64-bit action field is placed at offset 32, while pid is at offset 28.
    • When reading the trace (e.g., through /sys/kernel/tracing/trace or trace_pipe), print_one_line() casts iter->ent to const struct blk_io_trace2 *t and evaluates:
      what = (t->action & ((1 << BLK_TC_SHIFT) - 1)) & ~__BLK_TA_CGROUP;
      
      Because of the layout mismatch, t->action reads the bytes from v1's pid field (offset 32). If the process PID satisfies (pid & 0xFFFF) == 14, what is evaluated as 14.
  2. Unchecked Function Pointer Call on Uninitialized Array Slot:

    • what2act[] is defined using designated initializers up to [__BLK_TA_REMAP] = 15, making ARRAY_SIZE(what2act) == 16:
      static const struct {
          const char *act[2];
          void (*print)(struct trace_seq *s, const struct trace_entry *ent, bool has_cg);
      } what2act[] = {
          [__BLK_TA_QUEUE]       = {{ "Q", "queue" },       blk_log_generic },
          ...
          [__BLK_TA_SPLIT]       = {{ "X", "split" },       blk_log_split },
          [__BLK_TA_REMAP]       = {{ "A", "remap" },       blk_log_remap },
      };
      
    • In enum blktrace_act, index 14 is __BLK_TA_BOUNCE (/* unused, was: bio was bounced */). It is completely omitted in what2act[], leaving what2act[14].act = {NULL, NULL} and what2act[14].print = NULL.
    • In print_one_line():
      if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act)))
          trace_seq_printf(s, "Unknown action %x\n", what);
      else {
          log_action(iter, what2act[what].act[long_act], has_cg);
          what2act[what].print(s, iter->ent, has_cg);
      }
      
    • When what == 14, the check what == 0 || what >= ARRAY_SIZE(what2act) evaluates to false (14 < 16).
    • print_one_line() fails to check whether what2act[what].print is non-NULL.
    • It attempts to call what2act[14].print(...) (NULL), triggering an instruction fetch page fault at RIP: 0x0 in kernel mode (#PF: supervisor instruction fetch in kernel mode).

Runtime Impact and Classification

  • Memory Corruption (MemoryCorruption: false): The crash occurs directly from calling an uninitialized NULL function pointer (RIP: 0010:0x0), not a wild or corrupted pointer. In production builds without debugging sanitizers, this is a pure NULL pointer dereference and instruction fetch fault; it does not corrupt kernel memory or hijack control flow to attacker-chosen payload addresses.
  • Information Leak (InfoLeak: "none"): No kernel heap/stack data or pointers are leaked to userspace; the read operation immediately faults and crashes.
  • Denial of Service (RawDenialOfService: true): Dereferencing the NULL pointer causes an immediate kernel oops/panic during standard read() operations on the trace file, halting the calling process or the entire system depending on panic_on_oops configuration.
  • Candidate Subsystems (IsNetCandidate: false, IsKVMCandidate: false): The issue is entirely within the block tracing subsystem (blktrace) and generic tracing infrastructure (ftrace).
▶ ▼ ✨ AI Jobs (2)
ID Workflow Result Correct Bug Created Started Finished Revision
c4f25cc9 repro-c Reproduced: ✅ ❓ BUG: unable to handle kernel NULL pointer dereference in print_one_line 2026/11/03 00:03 2026/11/03 00:03 2026/11/03 01:03 0a94d799
c5317980 assessment-security DenialOfService: ✅ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ BUG: unable to handle kernel NULL pointer dereference in print_one_line 2026/10/31 07:21 2026/10/31 07:21 2026/10/31 08:05 2041d3f8
▶ ▼ Discussions (2)
Title Replies (including bot) Last reply
[PATCH] blktrace: always record v2 format for the ftrace tracer 1 (1) 2026/11/04 14:39
[syzbot] [trace?] [block?] BUG: unable to handle kernel NULL pointer dereference in print_one_line 0 (1) 2026/11/04 06:50
▶ ▼ Last patch testing requests (1)
Created Duration User Patch Repo Result
2026/11/03 02:11 24m retest repro git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 2637bdec0535a2044cd830eba9a79363651d9043 report job log log

Sample crash report:
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor instruction fetch in kernel mode
#PF: error_code(0x0010) - not-present page
PGD 0 P4D 0 
Oops: Oops: 0010 [#1] SMP KASAN PTI
CPU: 1 UID: 0 PID: 6058 Comm: syz-executor155 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/15/2026
RIP: 0010:0x0
Code: Unable to access opcode bytes at 0xffffffffffffffd6.
RSP: 0018:ffffc900039cf9f8 EFLAGS: 00010206
RAX: 1ffff1100f6dc81e RBX: 0000000000000000 RCX: ffff888027a8ddc0
RDX: 0000000000000001 RSI: ffff88807b428004 RDI: ffff88807b6e20f0
RBP: ffffffff8c334eb0 R08: ffff88807b6e215d R09: 1ffff1100f6dc42b
R10: dffffc0000000000 R11: 0000000000000000 R12: ffff88807b6e0000
R13: ffffffff81d21760 R14: ffff88807b6e20f0 R15: ffff88807b6e40f0
FS:  000055555b9db400(0000) GS:ffff8881234ff000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffffffffd6 CR3: 000000005d394000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 print_one_line+0x29d/0x300 kernel/trace/blktrace.c:1757
 s_show+0x142/0x320 kernel/trace/trace.c:3332
 seq_read_iter+0x8d5/0xca0 fs/seq_file.c:273
 seq_read+0x367/0x480 fs/seq_file.c:163
 vfs_read+0x213/0xa80 fs/read_write.c:572
 ksys_read+0x150/0x270 fs/read_write.c:716
 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
 do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fc3268e9437
Code: 48 89 fa 4c 89 df e8 98 1e 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007ffe64d7f280 EFLAGS: 00000202 ORIG_RAX: 0000000000000000
RAX: ffffffffffffffda RBX: 000055555b9db400 RCX: 00007fc3268e9437
RDX: 0000000000001000 RSI: 00007ffe64d7f530 RDI: 0000000000000005
RBP: 0000000000000005 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fc326926928
R13: 0000000000000004 R14: 00007ffe64d7f430 R15: 00007ffe64d7f2fc
 </TASK>
Modules linked in:
CR2: 0000000000000000
---[ end trace 0000000000000000 ]---
RIP: 0010:0x0
Code: Unable to access opcode bytes at 0xffffffffffffffd6.
RSP: 0018:ffffc900039cf9f8 EFLAGS: 00010206
RAX: 1ffff1100f6dc81e RBX: 0000000000000000 RCX: ffff888027a8ddc0
RDX: 0000000000000001 RSI: ffff88807b428004 RDI: ffff88807b6e20f0
RBP: ffffffff8c334eb0 R08: ffff88807b6e215d R09: 1ffff1100f6dc42b
R10: dffffc0000000000 R11: 0000000000000000 R12: ffff88807b6e0000
R13: ffffffff81d21760 R14: ffff88807b6e20f0 R15: ffff88807b6e40f0
FS:  000055555b9db400(0000) GS:ffff8881234ff000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffffffffd6 CR3: 000000005d394000 CR4: 00000000003526f0

Crashes (2):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/03 02:36 git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git 2637bdec0535 0ec395f8 .config console log report C ci-upstream-linux-next-kasan-gce-root BUG: unable to handle kernel NULL pointer dereference in print_one_line
2026/10/31 06:38 linux-next 7649ba73f9e7 0ec395f8 .config console log report info [disk image] [vmlinux] [kernel image] ci-upstream-linux-next-kasan-gce-root BUG: unable to handle kernel NULL pointer dereference in print_one_line
* Struck through repros no longer work on HEAD.