syzbot
WARNING in devlink_free (2)
Status:
moderation: reported on 2026/11/14 10:50
Subsystems:
net
Labels:
prio:low
[Documentation on labels]
Reported-by: syzbot+75f25d90d774273f7282@syzkaller.appspotmail.com
First crash: 2h07m, last: 2h07m
β¨ AI-generated root cause summary:
In netdevsim, switchdev eswitch mode can be enabled with zero VFs configured, allowing userspace to create devlink rate nodes via netlink. However, during device teardown or reload in nsim_dev_reload_destroy(), the cleanup call to nsim_esw_legacy_enable()βwhich invokes devl_rate_nodes_destroy()βis conditionally guarded by if (nsim_dev_get_vfs(nsim_dev)). When VFs were never configured (num_vfs == 0), nsim_esw_legacy_enable() is bypassed, leaving devlink_rate nodes in devlink->rate_list and triggering the WARN_ON(devlink_rates_check(devlink, NULL, NULL)) sanity check in devlink_free().
▶
▼
β¨ Full AI root cause analysis
Root Cause Analysis
Involved Functions, Structs, and Files
- Files:
- Functions:
- Structs and Fields:
struct nsim_dev (esw_mode)
struct devlink (rate_list)
struct devlink_rate (type == DEVLINK_RATE_TYPE_NODE, list, priv, name)
Bug Mechanism and Lifecycle Invariant Violation
-
Switchdev Mode Allowed With Zero VFs:
When userspace configures the netdevsim eswitch mode via Netlink (DEVLINK_CMD_ESWITCH_MODE_SET with DEVLINK_ESWITCH_MODE_SWITCHDEV), nsim_devlink_eswitch_mode_set() invokes nsim_esw_switchdev_enable(). In this function:
for (i = 0; i < nsim_dev_get_vfs(nsim_dev); i++) {
...
}
nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
If no VFs have been instantiated (nsim_dev_get_vfs(nsim_dev) == 0), the loop does not run, but nsim_dev->esw_mode is successfully set to DEVLINK_ESWITCH_MODE_SWITCHDEV.
-
Creation of Rate Nodes:
Once in switchdev mode, userspace creates one or more devlink rate nodes using DEVLINK_CMD_RATE_NEW (devlink_nl_rate_new_doit()). The driver callback nsim_rate_node_new() checks:
if (!nsim_esw_mode_is_switchdev(nsim_dev)) {
NL_SET_ERR_MSG_MOD(extack, "Node creation allowed only in switchdev mode.");
return -EOPNOTSUPP;
}
Because nsim_dev->esw_mode is DEVLINK_ESWITCH_MODE_SWITCHDEV, node creation succeeds regardless of the number of VFs. An allocated struct devlink_rate object of type DEVLINK_RATE_TYPE_NODE is added to devlink->rate_list.
-
Incomplete Teardown in nsim_dev_reload_destroy():
When the netdevsim device is removed (nsim_drv_remove()) or reloaded (nsim_dev_reload_down()), nsim_dev_reload_destroy() is called to tear down sub-components. The destruction of rate nodes is handled within nsim_esw_legacy_enable(), which calls devl_rate_nodes_destroy(devlink).
However, nsim_dev_reload_destroy() guards the eswitch transition with a VF existence check:
if (nsim_dev_get_vfs(nsim_dev)) {
nsim_bus_dev_set_vfs(nsim_dev->nsim_bus_dev, 0);
if (nsim_esw_mode_is_switchdev(nsim_dev))
nsim_esw_legacy_enable(nsim_dev, NULL);
}
Because nsim_dev_get_vfs(nsim_dev) is 0, the entire block is bypassed. nsim_esw_legacy_enable() is not executed, and devl_rate_nodes_destroy() is never called.
-
Failure Trigger:
Execution proceeds to devlink_free(devlink) in nsim_drv_remove(). Line 544 of net/devlink/core.c checks whether any rate elements remain registered on the devlink instance:
WARN_ON(devlink_rates_check(devlink, NULL, NULL));
Because the user-created devlink_rate node(s) were never destroyed and remain linked in devlink->rate_list, devlink_rates_check() returns -EBUSY, tripping the WARN_ON.
Sample crash report:
netdevsim netdevsim0 netdevsim0 (unregistering): unset [0, 0] type 1 family 0 port 8472 - 0
netdevsim netdevsim0 netdevsim0 (unregistering): unset [1, 0] type 2 family 0 port 6081 - 0
netdevsim netdevsim0 netdevsim0 (unregistering): unset [1, 1] type 2 family 0 port 20004 - 0
------------[ cut here ]------------
devlink_rates_check(devlink, NULL, NULL)
WARNING: net/devlink/core.c:544 at devlink_free+0x359/0x450 net/devlink/core.c:544, CPU#1: syz-executor/17425
Modules linked in:
CPU: 1 UID: 0 PID: 17425 Comm: syz-executor Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/06/2026
RIP: 0010:devlink_free+0x359/0x450 net/devlink/core.c:544
Code: 00 e8 fb 62 e8 f6 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 e6 62 e8 f6 90 0f 0b 90 e9 02 fd ff ff e8 d8 62 e8 f6 90 <0f> 0b 90 e9 29 fd ff ff e8 ca 62 e8 f6 90 0f 0b 90 e9 59 fd ff ff
RSP: 0018:ffffc900038a78b8 EFLAGS: 00010293
RAX: ffffffff8ae0be08 RBX: ffff8880797aa000 RCX: ffff8880546a9f40
RDX: 0000000000000000 RSI: 00000000fffffff0 RDI: 0000000000000000
RBP: 00000000fffffff0 R08: ffffffff91be00bf R09: 1ffffffff237c017
R10: dffffc0000000000 R11: 0000000000000000 R12: dffffc0000000000
R13: 1ffff1100f2f5400 R14: ffff8880797aa1f8 R15: ffff8880797aa3e0
FS: 000055557a90f500(0000) GS:ffff888123508000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fd61b5f0ce0 CR3: 000000002bf22000 CR4: 00000000003526f0
Call Trace:
<TASK>
nsim_drv_remove+0x146/0x170 drivers/net/netdevsim/dev.c:1736
device_remove drivers/base/dd.c:617 [inline]
__device_release_driver drivers/base/dd.c:1357 [inline]
device_release_driver_internal+0x42b/0x7d0 drivers/base/dd.c:1380
bus_remove_device+0x444/0x560 drivers/base/bus.c:678
device_del+0x524/0x8f0 drivers/base/core.c:3967
device_unregister+0x21/0xf0 drivers/base/core.c:4008
nsim_bus_dev_del drivers/net/netdevsim/bus.c:488 [inline]
del_device_store+0x2b5/0x370 drivers/net/netdevsim/bus.c:243
kernfs_fop_write_iter+0x3a4/0x540 fs/kernfs/file.c:345
new_sync_write fs/read_write.c:575 [inline]
vfs_write+0x612/0xba0 fs/read_write.c:667
ksys_write+0x150/0x270 fs/read_write.c:719
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x16a/0x530 arch/x86/entry/syscall_64.c:89
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7ffbf2169d0e
Code: 08 0f 85 a5 a8 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 80 00 00 00 00 48 83 ec 08
RSP: 002b:00007ffef50b4238 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000055557a90f500 RCX: 00007ffbf2169d0e
RDX: 0000000000000001 RSI: 00007ffef50b42c0 RDI: 0000000000000005
RBP: 00007ffbf223891c R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007ffef50b42c0 R14: 00007ffef50b4b00 R15: 0000000000000003
</TASK>
* Struck through repros no longer work on HEAD.