[Kernel Bug] BUG: unable to handle kernel paging request in dt2815_attach
From: Zhiyu Zhang
Date: Sun Dec 28 2025 - 13:19:06 EST
Dear Linux kernel developers and maintainers,
We are writing to report a Linux kernel bug titled "BUG: unable to
handle kernel paging request in dt2815_attach" found on Linux 6.17.1.
We also tested the PoC on the latest Linux 6.19-rc2 and can still
trigger a kernel panic.
The possible root cause is that the legacy COMEDI_DEVCONFIG ioctl path
(CAP_SYS_ADMIN) allows userspace to supply comedi_devconfig.options[],
and dt2815_attach() uses options[0] as the I/O base and immediately
performs port I/O during attach. Specifically, the reproducer triggers
comedi_unlocked_ioctl() -> do_devconfig_ioctl() ->
comedi_device_attach() -> dt2815_attach(). After do_devconfig_ioctl()
copies comedi_devconfig from userspace, the driver’s attach routine
uses options[0] as the I/O port base: comedi_request_region() is
called with this value and, on success, dev->iobase is set
accordingly. The driver then issues outb()/inb() to dev->iobase +
DT2815_STATUS/DT2815_DATA as part of its initialization sequence.
Physically, options[0] is meant to match the real DT2815 board's I/O
base configured by hardware. However, the provided iobase can be an
extreme/invalid value that does not correspond to a real DT2815
device. In such cases, dt2815_attach() ends up performing I/O accesses
to unrelated or nonexistent ports. The behavior of reads/writes to
such ports is inherently undefined and may depend on
platform/emulation and instrumentation; in our tests this leads to a
kernel panic during attach.
Importantly, we observed that the crash is sensitive to the specific
iobase value in our environment: using options[0] = 0x7d reproducibly
triggers a panic during attach on a fresh boot, while changing
options[0] to nearby or other values (e.g., 0x3d, 0x7a, 0x7e, 0x98,
0x17d) does not trigger a panic.
We also noticed that dt2815_attach() returns success even if the
initialization handshake never reaches the expected "ready" status
(the 100 wait loop finishes without meeting the condition). This
"success-on-failure" behavior can leave the device marked attached
despite being absent/unresponsive, increasing the likelihood of later
failures.
We suggest the following potential patch directions:
1. Fail attach when initialization does not complete. If the expected
ready status is not observed within the wait loop, return an error
(e.g., -ETIMEDOUT/-ENODEV) instead of 0.
2. Avoid unsafe writes before establishing presence. Perform a
conservative read-first probe and fail early if the device clearly
does not respond, instead of issuing outb() to an arbitrary base.
The bug report, kernel config, Syz reproducer, C reproducer, and
console output are attached to help with analysis. The KASAN report is
also listed below:
BUG: unable to handle page fault for address: ffffffff88fca316
#PF: supervisor write access in kernel mode
#PF: error_code(0x0003) - permissions violation
PGD e385067 P4D e385067 PUD e386063 PMD 8e001a1
Oops: Oops: 0003 [#1] SMP KASAN NOPTI
CPU: 2 UID: 0 PID: 14536 Comm: syz.7.8 Not tainted 6.17.1 #1 PREEMPT(full)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:__outb arch/x86/include/asm/shared/io.h:22 [inline]
RIP: 0010:dt2815_attach drivers/comedi/drivers/dt2815.c:199 [inline]
RIP: 0010:dt2815_attach+0x47b/0x6d0 drivers/comedi/drivers/dt2815.c:139
Code: 60 31 ff 44 89 e6 e8 d4 30 be f8 45 84 e4 74 1d e8 ea 35 be f8
41 80 3f 00 0f 85 b3 01 00 00 41 0f b7 85 d0 01 00 00 8d 50 01 <31> 66
90 e8 cd 35 be f8 83 c5 01 bf 64 00 00 00 89 ee e8 fe 30 be
RSP: 0018:ffffc9002b10f9e8 EFLAGS: 00010246
RAX: 000000000000007d RBX: 00000000000000ff RCX: ffffffff88fca37c
RDX: 000000000000007e RSI: ffffffff88fca386 RDI: 0000000000000001
RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000060 R11: 0000000000000000 R12: 0000000000000060
R13: ffff888022ab9000 R14: 0000000000000000 R15: ffffed100455723a
FS: 00007f5fe33e5640(0000) GS:ffff8880ce9be000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffff88fca316 CR3: 000000003fb8c000 CR4: 0000000000752ef0
PKRU: 80000000
Call Trace:
<TASK>
comedi_device_attach+0x3b0/0x900 drivers/comedi/drivers.c:1007
do_devconfig_ioctl+0x1b1/0x710 drivers/comedi/comedi_fops.c:872
comedi_unlocked_ioctl+0x165d/0x2f00 drivers/comedi/comedi_fops.c:2178
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:598 [inline]
__se_sys_ioctl fs/ioctl.c:584 [inline]
__x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:584
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x5677dd
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48
89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d
01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f5fe33e4fc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000007c5fa0 RCX: 00000000005677dd
RDX: 0000200000000180 RSI: 0000000040946400 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00000000007c6038 R14: 00000000007c5fa0 R15: 00007f5fe33c5000
</TASK>
Modules linked in:
CR2: ffffffff88fca316
---[ end trace 0000000000000000 ]---
RIP: 0010:__outb arch/x86/include/asm/shared/io.h:22 [inline]
RIP: 0010:dt2815_attach drivers/comedi/drivers/dt2815.c:199 [inline]
RIP: 0010:dt2815_attach+0x47b/0x6d0 drivers/comedi/drivers/dt2815.c:139
Code: 60 31 ff 44 89 e6 e8 d4 30 be f8 45 84 e4 74 1d e8 ea 35 be f8
41 80 3f 00 0f 85 b3 01 00 00 41 0f b7 85 d0 01 00 00 8d 50 01 <31> 66
90 e8 cd 35 be f8 83 c5 01 bf 64 00 00 00 89 ee e8 fe 30 be
RSP: 0018:ffffc9002b10f9e8 EFLAGS: 00010246
RAX: 000000000000007d RBX: 00000000000000ff RCX: ffffffff88fca37c
RDX: 000000000000007e RSI: ffffffff88fca386 RDI: 0000000000000001
RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000060 R11: 0000000000000000 R12: 0000000000000060
R13: ffff888022ab9000 R14: 0000000000000000 R15: ffffed100455723a
FS: 00007f5fe33e5640(0000) GS:ffff8880ce9be000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffff88fca316 CR3: 000000003fb8c000 CR4: 0000000000752ef0
PKRU: 80000000
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 31 ff xor %edi,%edi
2: 44 89 e6 mov %r12d,%esi
5: e8 d4 30 be f8 call 0xf8be30de
a: 45 84 e4 test %r12b,%r12b
d: 74 1d je 0x2c
f: e8 ea 35 be f8 call 0xf8be35fe
14: 41 80 3f 00 cmpb $0x0,(%r15)
18: 0f 85 b3 01 00 00 jne 0x1d1
1e: 41 0f b7 85 d0 01 00 movzwl 0x1d0(%r13),%eax
25: 00
26: 8d 50 01 lea 0x1(%rax),%edx
* 29: 31 66 90 xor %esp,-0x70(%rsi) <-- trapping instruction
2c: e8 cd 35 be f8 call 0xf8be35fe
31: 83 c5 01 add $0x1,%ebp
34: bf 64 00 00 00 mov $0x64,%edi
39: 89 ee mov %ebp,%esi
3b: e8 .byte 0xe8
3c: fe (bad)
3d: 30 .byte 0x30
3e: be .byte 0xbe
<<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>
Hope these would be of help. Please let me know if any further
information is required.
Best regards,
Zhiyu Zhang
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
uint64_t r[1] = {0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul,
/*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul,
/*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul,
/*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul,
/*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
// openat$comedi arguments: [
// fd: const = 0xffffffffffffff9c (8 bytes)
// file: ptr[in, buffer] {
// buffer: {2f 64 65 76 2f 63 6f 6d 65 64 69 33 00} (length 0xd)
// }
// flags: open_flags = 0x400 (4 bytes)
// mode: const = 0x0 (2 bytes)
// ]
// returns fd_comedi
memcpy((void*)0x200000000080, "/dev/comedi3\000", 13);
res =
syscall(__NR_openat, /*fd=*/0xffffffffffffff9cul,
/*file=*/0x200000000080ul, /*flags=O_APPEND*/ 0x400, /*mode=*/0);
if (res != -1)
r[0] = res;
// ioctl$COMEDI_DEVCONFIG arguments: [
// fd: fd_comedi (resource)
// cmd: const = 0x40946400 (4 bytes)
// arg: ptr[in, comedi_devconfig] {
// comedi_devconfig {
// board_name: buffer: {64 74 32 38 31 35 00 00 00 00 00 00 00 00 00 00
// 00 00 00 00} (length 0x14) options: array[int32] {
// int32 = 0x7d (4 bytes)
// int32 = 0x9 (4 bytes)
// int32 = 0x2 (4 bytes)
// int32 = 0x3 (4 bytes)
// int32 = 0x5 (4 bytes)
// int32 = 0xcc5 (4 bytes)
// int32 = 0xf (4 bytes)
// int32 = 0x7 (4 bytes)
// int32 = 0xa (4 bytes)
// int32 = 0xe8aa (4 bytes)
// int32 = 0x2 (4 bytes)
// int32 = 0x1 (4 bytes)
// int32 = 0xffffbffd (4 bytes)
// int32 = 0x1 (4 bytes)
// int32 = 0x0 (4 bytes)
// int32 = 0x0 (4 bytes)
// int32 = 0x0 (4 bytes)
// int32 = 0x1a44c (4 bytes)
// int32 = 0x3ff (4 bytes)
// int32 = 0x40000003 (4 bytes)
// int32 = 0x99 (4 bytes)
// int32 = 0xcaaa (4 bytes)
// int32 = 0x0 (4 bytes)
// int32 = 0x20001e57 (4 bytes)
// int32 = 0x7 (4 bytes)
// int32 = 0xe6b (4 bytes)
// int32 = 0x2 (4 bytes)
// int32 = 0xd0 (4 bytes)
// int32 = 0x2 (4 bytes)
// int32 = 0x1 (4 bytes)
// int32 = 0xfcc (4 bytes)
// int32 = 0x0 (4 bytes)
// }
// }
// }
// ]
memcpy((void*)0x200000000180,
"dt2815\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 20);
*(uint32_t*)0x200000000194 = 0x7d;
*(uint32_t*)0x200000000198 = 9;
*(uint32_t*)0x20000000019c = 2;
*(uint32_t*)0x2000000001a0 = 3;
*(uint32_t*)0x2000000001a4 = 5;
*(uint32_t*)0x2000000001a8 = 0xcc5;
*(uint32_t*)0x2000000001ac = 0xf;
*(uint32_t*)0x2000000001b0 = 7;
*(uint32_t*)0x2000000001b4 = 0xa;
*(uint32_t*)0x2000000001b8 = 0xe8aa;
*(uint32_t*)0x2000000001bc = 2;
*(uint32_t*)0x2000000001c0 = 1;
*(uint32_t*)0x2000000001c4 = 0xffffbffd;
*(uint32_t*)0x2000000001c8 = 1;
*(uint32_t*)0x2000000001cc = 0;
*(uint32_t*)0x2000000001d0 = 0;
*(uint32_t*)0x2000000001d4 = 0;
*(uint32_t*)0x2000000001d8 = 0x1a44c;
*(uint32_t*)0x2000000001dc = 0x3ff;
*(uint32_t*)0x2000000001e0 = 0x40000003;
*(uint32_t*)0x2000000001e4 = 0x99;
*(uint32_t*)0x2000000001e8 = 0xcaaa;
*(uint32_t*)0x2000000001ec = 0;
*(uint32_t*)0x2000000001f0 = 0x20001e57;
*(uint32_t*)0x2000000001f4 = 7;
*(uint32_t*)0x2000000001f8 = 0xe6b;
*(uint32_t*)0x2000000001fc = 2;
*(uint32_t*)0x200000000200 = 0xd0;
*(uint32_t*)0x200000000204 = 2;
*(uint32_t*)0x200000000208 = 1;
*(uint32_t*)0x20000000020c = 0xfcc;
*(uint32_t*)0x200000000210 = 0;
syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0x40946400,
/*arg=*/0x200000000180ul);
return 0;
}
Attachment:
repro.log
Description: Binary data
Attachment:
report0
Description: Binary data
Attachment:
repro.syz
Description: Binary data
Attachment:
6.17.0.config
Description: XML document
Attachment:
6.19-rc1.config
Description: XML document