Search Results (1712 CVEs found)

CVE Vendors Products Updated CVSS v3.1
CVE-2026-98441 1 Linux 1 Linux Kernel 2026-10-24 7.8 High
In the Linux kernel, the following vulnerability has been resolved: net/sched: act_ct: avoid modifying shared unconfirmed ct entry In a case where skb with an unconfirmed ct entry gets cloned, we may end up processing both again but with different sets of extensions. The series of events: 1. The first clone wants to commit and runs the helpers wiring up the extension pointer into the expectation list. 2. Then it looses the confirmation keeping the entry unconfirmed. 3. Second clone now wants to commit labels or run NAT and adds the new extension for that breaking the pointer in the expectation list causing UAF on the destruction path later. While this is possible to trigger, there should be no practical network pipeline where we need to process both clones without modifications in the same zone. So, let's just reset the entry in case for some reason we got an skb with a shared one. This doesn't affect any known use cases, but avoids any potential problems with sharing and modification of the unconfirmed ct entry. Unlike openvswitch module, act_ct allows for NAT without commit. Changing that would be a uAPI break. So, act_ct needs to reset on NAT regardless of the commit flag to avoid reallocation of the extension space. This, however, doesn't really change the picture for sensible networking cases as there should be no need to run the same packet twice (before and after the clone) through conntrack without packet header or zone changes and without commit. The fixes tag points to the introduction of helpers, since that's the main UAF trigger for the sharing.
CVE-2026-98383 1 Linux 1 Linux Kernel 2026-10-24 7.8 High
In the Linux kernel, the following vulnerability has been resolved: bpf: Disallow bpf_skb_pull_data() for LWT_SEG6LOCAL An LWT_SEG6LOCAL program can invalidate its cached SRH with bpf_lwt_seg6_adjust_srh() and then call bpf_skb_pull_data(). The latter may reallocate skb->head, leaving the per-CPU SRH pointer dangling. Post-program SRH validation then writes through that pointer. Disallow bpf_skb_pull_data() for LWT_SEG6LOCAL programs so the verifier rejects this unsafe helper combination. Other LWT program types continue to expose the helper through lwt_out_func_proto().
CVE-2026-98381 1 Linux 1 Linux Kernel 2026-10-24 7.8 High
In the Linux kernel, the following vulnerability has been resolved: veth: manage XDP program pointers during channel resize veth_set_channels() tears down XDP resources for removed RX queues without clearing rq->xdp_prog. If the program is then detached or replaced, those queues keep the old pointer after bpf_prog_put(). A later channel increase can re-enable NAPI and run the freed program. BUG: unable to handle page fault for address: ffffc90000256048 Oops: Oops: 0000 [#1] SMP KASAN NOPTI RIP: veth_xdp_rcv_skb (include/linux/filter.h:779 include/net/xdp.h:696 drivers/net/veth.c:820) Call Trace: veth_xdp_rcv (drivers/net/veth.c:941) veth_poll (drivers/net/veth.c:986) __napi_poll (net/core/dev.c:7787) net_rx_action (net/core/dev.c:7850 net/core/dev.c:8007) handle_softirqs (kernel/softirq.c:645) Kernel panic - not syncing: Fatal exception in interrupt
CVE-2026-98374 1 Linux 1 Linux Kernel 2026-10-24 8.8 High
In the Linux kernel, the following vulnerability has been resolved: tcp: fix use-after-free of retransmit_skb_hint in tcp_send_synack() When tcp_send_synack() replaces the cloned SYN skb at the head of the retransmit queue with a copy, it frees the original with tcp_rtx_queue_unlink_and_free() and only repairs tp->highest_sack. tp->retransmit_skb_hint keeps pointing at the freed skbuff_fclone_cache object. The dangling hint is read in tcp_verify_retransmit_hint() and used as the root of the rbtree walk in tcp_xmit_retransmit_queue(). An unprivileged TFO client (sendmsg(MSG_FASTOPEN)) can arm the hint with an attacker-supplied ICMP fragmentation-needed message, after which a simultaneous open frees the armed SYN skb: BUG: KASAN: slab-use-after-free in tcp_mark_skb_lost (net/ipv4/tcp_input.c:1316) Read of size 4 at addr ffff88800604d928 by task swapper/1/0 Call Trace: tcp_mark_skb_lost (net/ipv4/tcp_input.c:1316) tcp_simple_retransmit (net/ipv4/tcp_input.c:3158) tcp_v4_err (net/ipv4/tcp_ipv4.c:587) Sync the hint to the copy.
CVE-2026-98866 1 Linux 1 Linux Kernel 2026-10-24 4.7 Medium
In the Linux kernel, the following vulnerability has been resolved: sched/cache: Introduce task_struct->sched_cache_grp to fix UAF Add a sched_cache_grp pointer to task_struct so that scheduler code can access the cache group directly via the task, without going through mm->sched_cache_grp. This decouples the scheduler's hot-path accesses from the mm_struct. Each task holds its own refcount on the sched_cache_group, separate from the reference held by its mm_struct. The reference is acquired in copy_mm() (fork) and exec_mmap() (exec), and released in exit_mm(). This fixes the use-after-free when account_mm_sched() reaches the group through a task whose mm is being switched, as reported by Hyunwoo: https://lore.kernel.org/lkml/apPb-Dr4nPYuHQOK@v4bel/ Convert all scheduler code in fair.c and exit.c to use p->sched_cache_grp instead of p->mm->sched_cache_grp. Keep the fork/exec/exit reference management out of the generic mm paths: add sched_cache_fork(), sched_cache_fork_cleanup(), sched_cache_exec_mmap() and sched_cache_exit_mm() in kernel/sched/cache_sched.c (with empty stubs for !CONFIG_SCHED_CACHE), so fs/exec.c, kernel/fork.c and kernel/exit.c each call one helper instead of open-coding the refcounting under #ifdef. Also add sched_cache_group_get() and task_cache_group_get().
CVE-2026-98804 1 Linux 1 Linux Kernel 2026-10-24 4.7 Medium
In the Linux kernel, the following vulnerability has been resolved: net: page_pool: fix use-after-free in page_pool_recycle_ring_bulk() With CONFIG_PAGE_POOL_STATS=y, page_pool_recycle_ring_bulk() updates the recycle stats after dropping the producer lock. If it just recycled the last inflight netmems of a pool being destroyed, page_pool_release() can pass its producer-lock barrier and free the pool before recycle_stat_add() runs. Commit fcc680a647ba7 ("page_pool: allow mixing PPs within one bulk") moved this stat update after the unlock. Commit 271683bb2cf32 ("page_pool: Fix use-after-free in page_pool_recycle_in_ring") later added the barrier, but only fixed page_pool_recycle_in_ring(). Move the update back under the lock.
CVE-2026-98815 1 Linux 1 Linux Kernel 2026-10-24 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: nvme: fix cdev lifetime Sashiko bot reported a potential problem for the cdev lifetime in [0] - the code there is heavily based on the NVMe code. Currently the NS head .open and .release file_operations methods take and put a reference to the nvme_ns_head to ensure that this structure does not disappear while we open fds for that cdev. In multipath mode, when we teardown the NS head, we call nvme_cdev_del() -> cdev_device_del() -> cdev_del(). However after cdev_del() returns, cdevs already open will remain and their fops will still be callable. As such, we can still reference the cdev after the nvme_ns_head reference count drops to 0 (and is freed). This can be shown with an application which delays between opening the cdev and issuing the ioctl while the NS head is being torn down: # ./ioctl_file /dev/ng1n1 & # waiting 10 seconds .... # ./ini_nvme_teardown.sh [ 21.221718] nvme nvme1: Removing ctrl: NQN "nvme-test-target" [ 21.274609] nvme nvme2: Removing ctrl: NQN "nvme-test-target" # now going to issue ioctl .... [ 26.549285] ================================================================== [ 26.550841] BUG: KASAN: slab-use-after-free in cdev_put.part.0+0x3d/0x40 [ 26.552352] Read of size 8 at addr ffff88811e7fa170 by task ioctl_file/237 [ 26.553805] [ 26.554227] CPU: 3 UID: 0 PID: 237 Comm: ioctl_file Not tainted 7.2.0-rc1-00004-g6852a10e32d4 #921 PREEMPT(lazy) [ 26.554236] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 26.554241] Call Trace: [ 26.554245] <TASK> [ 26.554248] dump_stack_lvl+0x68/0xa0 [ 26.554266] print_report+0x10d/0x5d0 [ 26.554276] ? __virt_addr_valid+0x21d/0x3f0 [ 26.554287] ? cdev_put.part.0+0x3d/0x40 [ 26.554292] kasan_report+0x96/0xd0 [ 26.554300] ? cdev_put.part.0+0x3d/0x40 [ 26.554307] cdev_put.part.0+0x3d/0x40 [ 26.554313] __fput+0x7bc/0xa70 [ 26.554322] fput_close_sync+0xd8/0x190 [ 26.554328] ? __pfx_fput_close_sync+0x10/0x10 [ 26.554337] __x64_sys_close+0x79/0xd0 [ 26.554344] do_syscall_64+0x117/0x6b0 [ 26.554351] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 26.554358] RIP: 0033:0x7f938c067727 [ 26.554364] Code: 48 89 fa 4c 89 df e8 28 ad 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 <5bf [ 26.554369] RSP: 002b:00007fff49f05980 EFLAGS: 00000202 ORIG_RAX: 0000000000000003 [ 26.554376] RAX: ffffffffffffffda RBX: 00007f938bfd7780 RCX: 00007f938c067727 [ 26.554380] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 [ 26.554383] RBP: 00007fff49f05a10 R08: 0000000000000000 R09: 0000000000000000 [ 26.554386] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 [ 26.554389] R13: 00007fff49f05b40 R14: 00007f938c207000 R15: 000055c148471d78 [ 26.554397] </TASK> [ 26.554399] [ 26.575612] Allocated by task 100: [ 26.575871] kasan_save_stack+0x24/0x50 [ 26.576157] kasan_save_track+0x14/0x30 [ 26.576418] __kasan_kmalloc+0x7f/0x90 [ 26.576668] __kmalloc_noprof+0x281/0x6c0 [ 26.576938] nvme_alloc_ns+0x7f7/0x3170 [ 26.577206] nvme_scan_ns+0x508/0x880 [ 26.577449] async_run_entry_fn+0x8c/0x350 [ 26.577723] process_scheduled_works+0xb6f/0x1a00 [ 26.578034] worker_thread+0x4ad/0xb40 [ 26.578283] kthread+0x34f/0x450 [ 26.578501] ret_from_fork+0x563/0x800 [ 26.578752] ret_from_fork_asm+0x1a/0x30 [ 26.579012] [ 26.579124] Freed by task 237: [ 26.579335] kasan_save_stack+0x24/0x50 [ 26.579596] kasan_save_track+0x14/0x30 [ 26.579855] kasan_save_free_info+0x3a/0x60 [ 26.580131] __kasan_slab_free+0x43/0x70 [ 26.580388] kfree+0x321/0x500 [ 26.580591] nvme_ns_head_chr_release+0x39/0x50 [ 26.580883] __fput+0x352/0xa70 [ 26.581095] fput_close_sync+0xd8/0x190 [ 26.581350] __x64_sys_close+0x79/0xd0 [ 26.581595] do_syscall_64+0x117/0x6b0 [ 26.581842] entry_SYSCAL ---truncated---
CVE-2026-98799 1 Linux 1 Linux Kernel 2026-10-24 4.4 Medium
In the Linux kernel, the following vulnerability has been resolved: bpf: Skip detached progs in trampoline images that are still in use bpf_tramp_image_put() makes sure a trampoline image is not freed while a task may still be running in it, but nothing similar is done for the progs called by that image. Detach drops the last prog reference right away and the prog is freed after grace periods, on the basis that a task still in the traced function skips the fexit progs once the nop at ip_after_call is patched to a jump. That leaves out a task sleeping in a sleepable prog that runs before the detached one, which no grace period waits for: CPU 0 CPU 1 in image I, sleeping in prog S detach P from I's trampoline -> new image, bpf_tramp_image_put(I) bpf_prog_put(P), last ref grace periods, P freed back from S __bpf_prog_enter(P) call P->bpf_func If S and P are fexit progs the task is already past the patched jump, and fentry only images don't have one. On x86 this is an int3 in poisoned bpf_prog_pack memory: Oops: int3: 0000 [#1] SMP NOPTI CPU: 18 UID: 0 PID: 94573 Comm: x169 Not tainted 6.18.44 #1 PREEMPT(lazy) RIP: 0010:0xffffffffc0601d8d Call Trace: <TASK> ? bpf_trampoline_6442515411+0x1a4/0x21b bpf_lsm_bprm_committed_creds+0x5/0x10 security_bprm_committed_creds+0x5f/0x70 begin_new_exec+0x2d6/0x410 ... We hit this in production when progs attached through trampolines got detached while their hooks were busy, and it was independently found with a fuzzer and KASAN. Have the JITs emit a patchable nop in front of each prog call sequence and record it in the image. When a prog is detached, patch its nop to a jump over the call sequence. Progs that stay attached keep running for the tasks that are in the image, and ip_after_call isn't needed anymore. The task can be in any image that isn't freed yet, not only in the current one. It sleeps in image I1 that calls S, P and Q, then P is detached and the trampoline moves to image I2, then Q is detached and its call is still in I1. So the trampoline keeps a list of its images until they are freed, and detaching a prog patches its nop in all of them. Images hold a reference on the trampoline for that long. On riscv and loongarch a jump of any range takes several instructions, and a task preempted in the middle of them could resume into half of the new sequence. The nop is a single instruction there, patched to a near branch through arch_bpf_trampoline_skip(). With the extra nops, BPF_MAX_TRAMP_LINKS progs no longer fit in a page on x86 and arm64 (and already didn't on powerpc), so lower the limit there like s390 does.
CVE-2026-111804 2 Apache, Apache Software Foundation 3 Apache Traffic Server, Traffic Server, Apache Traffic Server 2026-10-23 8.2 High
Apache Traffic Server's experimental wasm plugin has a use-after-free in its transaction-close handler and forwards unvalidated guest-supplied metric IDs to the internal stats API. This issue affects Apache Traffic Server: from 10.0.0 through 10.1.4, 10.2.0. Users are recommended to upgrade to version 10.1.5 or 10.2.1, which fix the issue.
CVE-2026-98758 1 Linux 1 Linux Kernel 2026-10-23 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: usb: typec: ucsi: glink: fix use-after-free of ucsi on remove The pmic_glink client is released by the devres cleanup, which runs after pmic_glink_ucsi_remove() has returned, so its notification callbacks can queue work until then. Work that runs after ucsi_unregister() has been called touches freed state: it dereferences the connector array that ucsi_unregister() freed, or registers and unregisters the instance a second time. Disable both work items with disable_work_sync() before unregistering, and unregister only if the instance is still registered. This issue was found by an in-house static analysis tool.
CVE-2026-98740 1 Linux 1 Linux Kernel 2026-10-23 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: EDAC/altera: Drop __init from ECC setup paths for re-probe safety Sashiko reports: "Does suppressing sysfs unbinding fully prevent the execution of freed __init memory? If altr_sysmgr_regmap_lookup_by_phandle() returns -EPROBE_DEFER, the probe is deferred until after __init memory is freed." The a10 EDAC .setup callbacks (sdmmc, ethernet, nand, dma, usb, qspi) and their helpers (altr_init_a10_ecc_device_type, altr_init_a10_ecc_block) were marked __init. These run from the probe path, which may execute after init memory is freed -- e.g. a probe deferred via -EPROBE_DEFER that only succeeds once a late/module dependency appears, or a manual unbind/rebind. Calling __init code then dereferences freed memory. Remove __init so these functions remain valid at runtime.
CVE-2026-99001 1 Linux 2 Linux, Linux Kernel 2026-10-23 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: drm/xe/i2c: cancel the client work on remove xe_i2c_notifier() stores the DesignWare adapter in i2c->adapter and schedules i2c->work when the adapter is registered under the xe I2C platform device, and xe_i2c_client_work() then instantiates the AMC client device on that adapter. xe_i2c_remove() tears down the AMC, unregisters the client devices, the bus notifier and the adapter platform device, but it never drains i2c->work. A work item that is still queued or running when the adapter is unregistered dereferences i2c->adapter in i2c_new_client_device() after platform_device_unregister() has released the adapter. The work item is also embedded in the devm-allocated struct xe_i2c, so a work item still queued after the drm device devm unwind frees that allocation runs its callback on freed memory. The bus notifier is the only thing that schedules this work, and it is unregistered after the client devices. An instance that is still queued when the teardown runs can therefore write i2c->client[XE_I2C_CLIENT_AMC] while the loop is unregistering and clearing the same array, and an AMC client it instantiates late is only cleaned up by the adapter's own child sweep in i2c_del_adapter(). Move bus_unregister_notifier() in front of the client teardown loop and cancel the work right after it, so no new instance can be scheduled and a queued instance is drained before the client array is touched. A running instance still finds a live adapter, since the adapter is unregistered later. (cherry picked from commit a23f27d5ec11c3f418c5e5531eea34ccda2b5b20)
CVE-2026-74534 1 Linux 1 Linux Kernel 2026-10-23 8.8 High
In the Linux kernel, the following vulnerability has been resolved: Bluetooth: ISO: fix refcounting of iso_conn iso_conn_del() and iso_chan_del() have a race that results to double-put of iso_conn: [Task hdev->workqueue] [Task 2] iso_conn_del iso_chan_del iso_conn_hold_unless_zero iso_conn_lock iso_conn_lock conn->sk = NULL iso_conn_unlock sk = iso_sock_hold(conn) <---------ยด if (!sk) iso_conn_put iso_conn_put iso_conn_put /* UAF */ The extra put for !sk in iso_conn_del() is currently required since failing iso_chan_add() may leave iso_conn not associated with any sk. Fix by having iso_pi(sk)->conn own refcount when non-NULL, so iso_conn_del does not need to put it. Adjust the iso_conn_add() refcounting so that conn is put if it does not get associated with an sk.
CVE-2026-98712 1 Linux 1 Linux Kernel 2026-10-23 6.5 Medium
In the Linux kernel, the following vulnerability has been resolved: KVM: arm64: vgic: Take a refcount on IRQs referenced by last_lr_irq Referencing the last interrupt inserted in an LR is rather fragile, as this interrupt can vanish if a concurrently unmapped LPI. Solve this by bumping up the refcount on the interrupt when populating last_lr_irq, and drop it at vgic_prune_ap_list() time, when LPIs are being reclaimed.
CVE-2026-98483 1 Linux 1 Linux Kernel 2026-10-22 5.5 Medium
In the Linux kernel, the following vulnerability has been resolved: nfc: fix use-after-free in nfc_get_local_general_bytes Commit 6709d4b7bc2e ("net: nfc: Fix use-after-free caused by nfc_llcp_find_local") attempted to fix a use-after-free (UAF) issue by invoking nfc_llcp_local_put(local) after accessing local->gb. However, if the reference count drops to zero, local is freed immediately, leading to a use-after-free when callers access the returned pointer. Alternative approaches using dynamic allocation (e.g. kmemdup) introduced memory leaks because callers consistently treat the returned pointer as borrowed memory. Fix this properly by refactoring nfc_llcp_general_bytes() and nfc_get_local_general_bytes() to accept a caller-provided output buffer (out_gb) and its maximum length (gb_max_len). The general bytes are safely copied into out_gb before calling nfc_llcp_local_put(local), ensuring safe lifetime management without ownership transfer complications. Update all callers across drivers (microread, pn533, pn544, st21nfca, digital_dep, and nci) to provide their own destination buffers and pass them to nfc_get_local_general_bytes().
CVE-2026-98606 1 Linux 1 Linux Kernel 2026-10-22 7.0 High
In the Linux kernel, the following vulnerability has been resolved: drm/virtio: release the GEM object on virtio_gpu_vram_create() errors virtio_gpu_vram_create() frees the object with a bare kfree(vram) on both error paths after drm_gem_private_object_init() has run, and on the second one after drm_gem_create_mmap_offset() has linked obj->vma_node into the device's VMA offset manager. The freed object stays in that interval tree, so a later lookup or insertion walks freed memory, and the dma_resv and gpuva lock are never destroyed. Call drm_gem_object_release() before kfree() on both paths.
CVE-2026-98617 1 Linux 1 Linux Kernel 2026-10-22 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: eth: fbnic: use the Rx queue napi pointer to find the napi vector The queue management ndos pick the napi vector for an Rx queue with: nv = fbn->napi[idx % fbn->num_napi]; The issue is this is only correct in the cases where there are no standalone Tx vectors. In those cases we were allocating the Tx vectors first and then the Rx so the queues would be pointing to Tx NAPI vectors instead of the Rx ones. The mapping the ndos want is already recorded. fbnic_set_netif_napi() publishes it with netif_queue_set_napi(), which stores the napi pointer in netdev_rx_queue.napi, and fbnic_reset_netif_napi() clears it again. Both run under the netdev instance lock that the queue management ndos also hold, so the pointer can be read directly. Use it and drop the divide. The pointer is NULL exactly while the datapath is down, so fbnic_queue_mem_alloc() can reject that case rather than reaching into freed state: netdev_rx_queue_restart() calls it before it tests netif_running(), and fbnic_pm_suspend() leaves netif_running() true across a PCIe recovery that never completes, so a queue restart can arrive after fbnic_stop() has freed the rings and the vectors. fbnic_stop() clears the association in fbnic_reset_netif_queues() before fbnic_free_napi_vectors(), so the NULL is always published first. fbnic_queue_start() and fbnic_queue_stop() need no check of their own, as netdev_rx_queue_reconfig() only reaches them once fbnic_queue_mem_alloc() has succeeded under the same instance lock.
CVE-2026-98625 1 Linux 1 Linux Kernel 2026-10-22 4.7 Medium
In the Linux kernel, the following vulnerability has been resolved: netfilter: flowtable: publish HW_DEAD after worker is done flow_offload_work_del() sets NF_FLOW_HW_DEAD before the work handler clears NF_FLOW_HW_PENDING. Once a flow is both HW_DYING and HW_DEAD, a concurrent garbage collection pass can remove it and schedule it for RCU freeing. The offload worker holds neither an RCU read lock nor a reference to the flow. If it is preempted after publishing HW_DEAD, the RCU callback can free the flow before the worker resumes and clears HW_PENDING, resulting in a use-after-free. Move HW_DEAD publication to the common worker epilogue after the pending bit is cleared, making it the final flow access by destroy work. Order all preceding flow accesses before publishing the bit that allows garbage collection to free the object.
CVE-2026-98632 1 Linux 1 Linux Kernel 2026-10-22 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: Bluetooth: mgmt: Dequeue pending mesh_send_sync entries on cancel In send_cancel(), pending mesh_tx objects are removed from the hdev->mesh_pending list and freed via mesh_send_complete(). However, if a mesh transmission was already queued onto hdev->cmd_sync_work_list via mesh_next(), the queued entry retains a raw pointer to mesh_tx. When hci_cmd_sync_work later processes the entry, it attempts to execute mesh_send_sync and its destroy callback mesh_send_start_complete using the already freed mesh_tx pointer, leading to a use-after-free. Fix this by invoking hci_cmd_sync_dequeue() for mesh_send_sync on the target mesh_tx before completing it. If the entry is found and dequeued, its destroy callback will complete and free the object; otherwise, mesh_send_complete() is called directly. Additionally, ensure the transmission queue advances after cancellation or errors. In mesh_send_start_complete(), call mesh_next() on error unless err is -ECANCELED, because hci_cmd_sync_dequeue() holds hdev->cmd_sync_work_lock and calling mesh_next() synchronously would deadlock. Instead, advance the queue in send_cancel() once the lock is released and if no transmission is in progress.
CVE-2026-98693 1 Linux 1 Linux Kernel 2026-10-22 4.1 Medium
In the Linux kernel, the following vulnerability has been resolved: thunderbolt: Hold a router reference for each allocated HopID tb_stop() drops the reference to all DP tunnels but does not deactivate them, thus nothing cancels a dprx_work still in flight (which holds its own tunnel reference) and the tunnel can outlive tb_switch_remove(). The HopID releases in tb_path_free() then operate on freed IDAs and trigger warnings like ida_free called for id=8 which is not allocated. This can be triggered by unbinding the driver while a DP tunnel is still waiting for the DPRX capabilities read to finish. On the Apple NHI unplugging the cable runs into just that reliably because the read can never finish right now and because the unplug powers down the entire USB4 complex and removes the NHI device. Take a router reference whenever an input or output HopID is allocated and drop it again after the HopID is released. This keeps the ports and their HopID IDAs alive for as long as they are used. The KUnit tests allocate routers without ever registering their devices so initialize the embedded struct device there as well and drop its initial reference when the test is finished.