memory leak in ndisc_send_rs (4)

Status: moderation: reported syz repro on 2026/11/12 23:31
Subsystems: net usb
Labels: prio:high
[Documentation on labels]
Reported-by: syzbot+a2b179071c4af7c71e5e@syzkaller.appspotmail.com
First crash: 6h00m, last: 6h00m
✨ AI-generated root cause summary:

In drivers/net/usb/hso.c, hso_net_start_xmit() takes ownership of an outgoing packet by stashing it in odev->skb_tx_buf when hso_get_activity() returns -EAGAIN (e.g. when the USB device is suspended, disconnected, or not configured). However, neither hso_net_close() nor hso_free_net_device() frees odev->skb_tx_buf prior to unregistering and freeing the net_device. When a packet (such as an IPv6 Router Solicitation generated during interface configuration) is queued during device disconnect or suspend, the sk_buff and its allocated head buffer are permanently leaked.

▶ ▼ ✨ Full AI root cause analysis
Based on kernel commit 9d66f26fefac:

Bug Analysis and Technical Breakdown

Root Cause

The memory leak is caused by improper lifecycle management of buffered transmit packets (sk_buff) in the Option HSO USB network driver (drivers/net/usb/hso.c).

Specifically:

  1. When a network packet is transmitted via hso_net_start_xmit() (drivers/net/usb/hso.c:766), the driver checks device activity via hso_get_activity(odev->parent).
  2. hso_get_activity() returns -EAGAIN if the underlying USB device is not in USB_STATE_CONFIGURED (e.g., when the device is suspended, disconnected, or tearing down: udev->state = USB_STATE_NOTATTACHED).
  3. On -EAGAIN, hso_net_start_xmit() buffers the packet in odev->skb_tx_buf and returns NETDEV_TX_OK:
    if (hso_get_activity(odev->parent) == -EAGAIN) {
        odev->skb_tx_buf = skb;
        return NETDEV_TX_OK;
    }
    
  4. By returning NETDEV_TX_OK, the driver assumes sole ownership of skb. However, drivers/net/usb/hso.c fails to free odev->skb_tx_buf:
    • Neither hso_net_close() nor hso_free_net_device() checks or calls dev_kfree_skb(odev->skb_tx_buf) before free_netdev(hso_net->net) frees struct hso_net.
    • Additionally, hso_net_open() resets odev->skb_tx_buf = NULL without freeing any previous buffer.

Trigger Mechanism

In the reproducer, a virtual USB device handled by hso is attached and its network interface is registered. Duplicate Address Detection (DAD) for IPv6 triggers addrconf_dad_work() -> addrconf_dad_completed() -> ndisc_send_rs() to send an ICMPv6 Router Solicitation packet. When the USB device disconnects or shuts down while this frame is queued, hso_get_activity() returns -EAGAIN. The Router Solicitation skb is stored into odev->skb_tx_buf. During driver teardown (hso_disconnect() -> hso_free_interface() -> hso_free_net_device()), the skb and its allocated data head buffer (kmalloc_reserve) are never released, triggering kmemleak reports for both objects.

Affected Components

  • File: drivers/net/usb/hso.c
  • Functions: hso_net_start_xmit(), hso_net_close(), hso_free_net_device(), hso_net_open()
  • Structs & Fields: struct hso_net::skb_tx_buf
▶ ▼ ✨ AI Jobs (1)
ID Workflow Result Correct Bug Created Started Finished Revision
68971053 assessment-security DenialOfService: ✅ Exploitable: ❌ FilesystemTrigger: ❌ FuzzingArtifact: ❌ MemoryCorruption: ❌ NetworkNeedsSetup: ❌ NetworkTrigger: ❌ PeripheralTrigger: ✅ RemoteTrigger: ❌ Unprivileged: ❌ UserNamespace: ❌ VMGuestTrigger: ❌ VMHostTrigger: ❌ ❓ memory leak in ndisc_send_rs (4) 2026/11/12 22:45 2026/11/12 22:45 2026/11/12 23:29 c0087d7f
▶ ▼ Similar bugs (3)
Kernel Title Rank 🛈 Repro Cause bisect Fix bisect Count Last Reported Patched Status
upstream memory leak in ndisc_send_rs net 3 syz, C 2 1854d 1901d 22/29 fixed on 2023/02/24 13:50
upstream memory leak in ndisc_send_rs (2) net 3 syz, C 1 1349d 1349d 0/29 closed as invalid on 2023/04/12 12:24
upstream memory leak in ndisc_send_rs (3) net 3 syz, C 1 1244d 1244d 0/29 closed as invalid on 2024/03/12 15:57

Sample crash report:
BUG: memory leak
unreferenced object 0xffff888100e9f200 (size 240):
  comm "kworker/u8:2", pid 5708, jiffies 4294993435
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 f2 e9 00 81 88 ff ff  ................
    00 20 bd 23 81 88 ff ff 80 31 48 02 81 88 ff ff  . .#.....1H.....
  backtrace (crc 28f53d77):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4733 [inline]
    slab_alloc_node mm/slub.c:5033 [inline]
    kmem_cache_alloc_node_noprof+0x368/0x400 mm/slub.c:5105
    __alloc_skb+0xdc/0x4e0 net/core/skbuff.c:705
    alloc_skb include/linux/skbuff.h:1390 [inline]
    ndisc_alloc_skb+0x46/0xf0 net/ipv6/ndisc.c:421
    ndisc_send_rs+0x49/0x2f0 net/ipv6/ndisc.c:708
    addrconf_dad_completed+0x1f9/0x6c0 net/ipv6/addrconf.c:4422
    addrconf_dad_begin net/ipv6/addrconf.c:4184 [inline]
    addrconf_dad_work+0x5c8/0x910 net/ipv6/addrconf.c:4289
    process_one_work+0x2b7/0x5c0 kernel/workqueue.c:3495
    process_scheduled_works kernel/workqueue.c:3578 [inline]
    worker_thread+0x255/0x4a0 kernel/workqueue.c:3659
    kthread+0x150/0x1a0 kernel/kthread.c:436
    ret_from_fork+0x219/0x490 arch/x86/kernel/process.c:158
    ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

BUG: memory leak
unreferenced object 0xffff888106538b00 (size 704):
  comm "kworker/u8:2", pid 5708, jiffies 4294993435
  hex dump (first 32 bytes):
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    60 00 00 00 00 08 3a ff fe 80 00 00 00 00 00 00  `.....:.........
  backtrace (crc 261f6968):
    kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
    slab_post_alloc_hook mm/slub.c:4733 [inline]
    slab_alloc_node mm/slub.c:5033 [inline]
    kmem_cache_alloc_node_noprof+0x368/0x400 mm/slub.c:5105
    kmalloc_reserve+0xd2/0x1b0 net/core/skbuff.c:616
    __alloc_skb+0x15d/0x4e0 net/core/skbuff.c:716
    alloc_skb include/linux/skbuff.h:1390 [inline]
    ndisc_alloc_skb+0x46/0xf0 net/ipv6/ndisc.c:421
    ndisc_send_rs+0x49/0x2f0 net/ipv6/ndisc.c:708
    addrconf_dad_completed+0x1f9/0x6c0 net/ipv6/addrconf.c:4422
    addrconf_dad_begin net/ipv6/addrconf.c:4184 [inline]
    addrconf_dad_work+0x5c8/0x910 net/ipv6/addrconf.c:4289
    process_one_work+0x2b7/0x5c0 kernel/workqueue.c:3495
    process_scheduled_works kernel/workqueue.c:3578 [inline]
    worker_thread+0x255/0x4a0 kernel/workqueue.c:3659
    kthread+0x150/0x1a0 kernel/kthread.c:436
    ret_from_fork+0x219/0x490 arch/x86/kernel/process.c:158
    ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245

connection error: failed to recv *flatrpc.ExecutorMessageRawT: EOF

Crashes (1):
Time Kernel Commit Syzkaller Config Log Report Syz repro C repro VM info Assets (help?) Manager Title
2026/11/12 17:51 upstream 9d66f26fefac d6166547 .config console log report syz / log [disk image] [vmlinux] [kernel image] ci-upstream-gce-leak memory leak in ndisc_send_rs
* Struck through repros no longer work on HEAD.