BUG: unable to handle kernel paging request in nsim_drv_port_add (2)

Status: upstream: reported C repro on 2026/11/01 07:01
Subsystems: net
Labels: prio:low
[Documentation on labels]
Reported-by: syzbot+b3fca27eb4005f0111f4@syzkaller.appspotmail.com
First crash: 4d04h, last: 20h12m
✨ AI-generated root cause summary:

In netdevsim, sysfs device attributes such as 'new_port' and 'del_port' are exposed at the device level on nsim_bus_dev without holding device_lock or checking if the driver is bound. An access via sysfs after the driver has been unbound, after a failed probe, or concurrently with device removal finds drvdata set to NULL; passing this NULL pointer to priv_to_devlink() computes a negative offset from NULL, triggering a kernel page fault crash when attempting to acquire devlink->lock.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 62c457528529:

Technical Analysis of the Kernel Crash

1. Root Cause Analysis

The defect is located in drivers/net/netdevsim/bus.c and drivers/net/netdevsim/dev.c.

In drivers/net/netdevsim/bus.c, device-level sysfs attributesβ€”including new_port, del_port, and sriov_numvfsβ€”are registered as part of nsim_bus_dev_type.groups on nsim_bus_dev->dev. The write handler new_port_store() attempts to guard against premature access by checking:

if (!smp_load_acquire(&nsim_bus_dev->init))
    return -EBUSY;

However, this check is insufficient for device and driver lifecycle management:

  1. Driver Unbind Lifecycle: When a user unbinds the driver (e.g. by writing the device name to /sys/bus/netdevsim/drivers/netdevsim/unbind), the driver core calls nsim_bus_remove() -> nsim_drv_remove(). In nsim_drv_remove(), the driver resources and devlink instances are torn down, and dev_set_drvdata(&nsim_bus_dev->dev, NULL) clears the driver private data. Crucially, the underlying nsim_bus_dev device remains registered on nsim_bus, its sysfs attribute files remain accessible, and nsim_bus_dev->init remains true (it is only cleared during del_device_store() -> nsim_bus_dev_del()).
  2. Missing Synchronization / Driver-Bound Check: new_port_store() does not acquire device_lock(&nsim_bus_dev->dev) nor does it verify that dev->driver is bound or dev_get_drvdata(&nsim_bus_dev->dev) is non-NULL before invoking nsim_drv_port_add(nsim_bus_dev, ...).
  3. Probe Failure & Concurrency Races: Similarly, if nsim_drv_probe() encounters an error during device initialization or if removal occurs concurrently with port creation, dev_get_drvdata(&nsim_bus_dev->dev) is NULL.

When nsim_drv_port_add() executes with drvdata == NULL:

int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
                      unsigned int port_index, u8 perm_addr[ETH_ALEN])
{
    struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
    int err;

    devl_lock(priv_to_devlink(nsim_dev));
    ...

nsim_dev is NULL. The helper priv_to_devlink() calculates:

container_of(priv, struct devlink, priv);

Since priv is NULL (0x0), subtracting offsetof(struct devlink, priv) (0x460 or 1120 bytes) yields a wrapped/negative pointer (struct devlink *)-0x460. Then devl_lock() calls mutex_lock(&devlink->lock). In struct devlink:

  • lock is located at offset 0x2b8 (696 bytes).
  • On the PREEMPT_RT kernel build with CONFIG_DEBUG_LOCK_ALLOC (as seen in the report), struct mutex contains struct rt_mutex_base rtmutex (size 0x58 / 88 bytes) followed by struct lockdep_map dep_map.
  • lock_acquire(&lock->dep_map, ...) is called with &devlink->lock.dep_map, which computes: $$-0x460 + 0x2b8 + 0x58 = -0x150 = \texttt{0xfffffffffffffeb0}$$ Inside __lock_acquire() at kernel/locking/lockdep.c:5140:
if (unlikely(lock->key == &__lockdep_no_track__))

The trapping instruction mov (%rdi), %rax attempts to dereference lock->key at address 0xfffffffffffffeb0, causing an immediate kernel page fault crash (#PF supervisor read access in kernel mode on an unmapped page).


2. Runtime Consequences in Production

  • Without Sanitizers and RT Debugging: In a production non-RT kernel without lockdep, mutex_lock(&devlink->lock) calls atomic_long_try_cmpxchg_acquire(&lock->owner, ...) targeting &devlink->lock.owner at offset $$-0x460 + 0x2b8 = -0x1a8 = \texttt{0xfffffffffffffe58}$$. The CPU attempts a supervisor write to that unmapped high address, triggering a kernel Oops/panic.
  • Memory Safety Impact: The fault is a deterministic NULL pointer dereference with a constant struct offset (underflowing to the unmapped canonical high address 0xfffffffffffffeb0 / 0xfffffffffffffe58). No arbitrary memory or valid slab object is corrupted, overwritten, or freed; hence, MemoryCorruption = false.
  • Information Leak: Execution terminates immediately at lock acquisition without reading or disclosing kernel data to userspace (InfoLeak = none).
  • Denial of Service: Any interaction with the sysfs attribute after driver unbinding triggers an unrecoverable kernel panic / denial of service (RawDenialOfService = true).
  • Subsystem Classification: The bug resides in drivers/net/netdevsim/, which provides a simulated network device driver in the network subsystem (IsNetCandidate = true), and does not involve virtualization or hypervisors (IsKVMCandidate = false).
▶ ▼ ✨ AI Jobs (2)
ID Workflow Result Correct Bug Created Started Finished Revision
8be38c30 repro-c Reproduced: βœ… ❓ BUG: unable to handle kernel paging request in nsim_drv_port_add (2) 2026/10/31 12:12 2026/10/31 12:12 2026/10/31 13:14 2041d3f8
94f4f745 assessment-security DenialOfService: βœ… Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ❌ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ BUG: unable to handle kernel paging request in nsim_drv_port_add (2) 2026/10/29 04:05 2026/10/29 04:05 2026/10/29 04:43 b1d00f76
▶ ▼ Discussions (1)
Title Replies (including bot) Last reply
[syzbot] [net?] BUG: unable to handle kernel paging request in nsim_drv_port_add (2) 1 (2) 2026/11/01 09:51
▶ ▼ Similar bugs (1)
Kernel Title Rank πŸ›ˆ Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream BUG: unable to handle kernel paging request in nsim_drv_port_add net 8 1 540d 540d 0/29 auto-obsoleted due to no activity on 2025/08/17 13:56
▶ ▼ Last patch testing requests (1)
Created Duration User Patch Repo Result
2026/10/31 14:46 35m retest repro git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 36aad21d50d1af3f6954bb0c988257a908202477 report job log log

Sample crash report:
BUG: unable to handle page fault for address: fffffffffffffeb0
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD f1b3067 P4D f1b3067 PUD f1b5067 PMD 0 
Oops: Oops: 0000 [#1] SMP KASAN PTI
CPU: 0 UID: 0 PID: 6031 Comm: syz-executor405 Not tainted syzkaller #0 PREEMPT_{RT,(full)} 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/15/2026
RIP: 0010:__lock_acquire+0x41/0x2de0 kernel/locking/lockdep.c:5140
Code: 2d 12 48 89 84 24 e0 00 00 00 65 48 8b 05 0f e3 2d 12 48 89 44 24 08 45 31 f6 83 3d 28 dc 32 0f 00 0f 84 90 14 00 00 48 89 fb <48> 8b 07 48 3d a0 69 92 94 0f 84 7e 14 00 00 45 89 cd 89 cd 41 89
RSP: 0018:ffffc900046978d8 EFLAGS: 00010002
RAX: ffff88801ff11f40 RBX: fffffffffffffeb0 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: fffffffffffffeb0
RBP: ffff88801ff11f40 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000100 R11: 0000000000000007 R12: fffffffffffffeb0
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000246
FS:  000055558a5ef400(0000) GS:ffff888124716000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffffffffffeb0 CR3: 00000000452a0000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 lock_acquire+0x115/0x350 kernel/locking/lockdep.c:5942
 __mutex_lock_common kernel/locking/rtmutex_api.c:561 [inline]
 mutex_lock_nested+0x55/0x1d0 kernel/locking/rtmutex_api.c:580
 nsim_drv_port_add+0x5a/0x140 drivers/net/netdevsim/dev.c:1760
 new_port_store+0x1a5/0x280 drivers/net/netdevsim/bus.c:96
 kernfs_fop_write_iter+0x3a5/0x540 fs/kernfs/file.c:345
 new_sync_write fs/read_write.c:595 [inline]
 vfs_write+0x61e/0xbb0 fs/read_write.c:687
 ksys_write+0x156/0x270 fs/read_write.c:739
 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:0x7efc00506777
Code: 48 89 fa 4c 89 df e8 58 1c 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:00007fff1f51a010 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000055558a5ef400 RCX: 00007efc00506777
RDX: 0000000000000002 RSI: 00007efc005586de RDI: 0000000000000003
RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff1f51a228
R13: 0000000000000002 R14: 00007efc005825a0 R15: 0000000000000002
 </TASK>
Modules linked in:
CR2: fffffffffffffeb0
---[ end trace 0000000000000000 ]---
RIP: 0010:__lock_acquire+0x41/0x2de0 kernel/locking/lockdep.c:5140
Code: 2d 12 48 89 84 24 e0 00 00 00 65 48 8b 05 0f e3 2d 12 48 89 44 24 08 45 31 f6 83 3d 28 dc 32 0f 00 0f 84 90 14 00 00 48 89 fb <48> 8b 07 48 3d a0 69 92 94 0f 84 7e 14 00 00 45 89 cd 89 cd 41 89
RSP: 0018:ffffc900046978d8 EFLAGS: 00010002
RAX: ffff88801ff11f40 RBX: fffffffffffffeb0 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: fffffffffffffeb0
RBP: ffff88801ff11f40 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000100 R11: 0000000000000007 R12: fffffffffffffeb0
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000246
FS:  000055558a5ef400(0000) GS:ffff888124716000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffffffffffeb0 CR3: 00000000452a0000 CR4: 00000000003526f0
----------------
Code disassembly (best guess):
   0:	2d 12 48 89 84       	sub    $0x84894812,%eax
   5:	24 e0                	and    $0xe0,%al
   7:	00 00                	add    %al,(%rax)
   9:	00 65 48             	add    %ah,0x48(%rbp)
   c:	8b 05 0f e3 2d 12    	mov    0x122de30f(%rip),%eax        # 0x122de321
  12:	48 89 44 24 08       	mov    %rax,0x8(%rsp)
  17:	45 31 f6             	xor    %r14d,%r14d
  1a:	83 3d 28 dc 32 0f 00 	cmpl   $0x0,0xf32dc28(%rip)        # 0xf32dc49
  21:	0f 84 90 14 00 00    	je     0x14b7
  27:	48 89 fb             	mov    %rdi,%rbx
* 2a:	48 8b 07             	mov    (%rdi),%rax <-- trapping instruction
  2d:	48 3d a0 69 92 94    	cmp    $0xffffffff949269a0,%rax
  33:	0f 84 7e 14 00 00    	je     0x14b7
  39:	45 89 cd             	mov    %r9d,%r13d
  3c:	89 cd                	mov    %ecx,%ebp
  3e:	41                   	rex.B
  3f:	89                   	.byte 0x89

Crashes (2):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/10/31 15:22 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 36aad21d50d1 96923c60 .config console log report C ci2-upstream-fs BUG: unable to handle kernel paging request in nsim_drv_port_add
2026/10/28 06:57 upstream 62c457528529 96923c60 .config console log report info [disk image] [vmlinux] [kernel image] ci2-upstream-fs BUG: unable to handle kernel paging request in nsim_drv_port_add
* Struck through repros no longer work on HEAD.