-
CVE-2026-98706
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: drain PS delivery work during station teardown
Removing an AP or mesh station can notify the driver and wake TXQs after
the station has already been removed from the driver, and can update
num_sta_ps and the power-save queues after station cleanup has purged
them.
sta_deliver_ps_frames() tests sta-dead only before it starts delivery. A
worker that passes that test can be delayed while teardown sets sta->dead
and removes the station from the driver; when it resumes it still runs the
full delivery.
The existing cancel_work_sync() sits near the end of
__cleanup_single_sta(), after the final driver state transition and after
PS accounting and queue purging, so it drains the worker only once the
state it has to protect has already changed. Before commit d34ba2168a3c
("mac80211: don't delay station destruction") cleanup was deferred
through the same ordered workqueue as the delivery work, which kept the
two ordered.
Cancel the work after setting sta->dead and before moving the driver
state, and move the existing cancellation to the start of
__cleanup_single_sta(). The first drain closes the driver-lifetime window;
driver callbacks during the remaining state transitions can still queue
drv_deliver_wk through ieee80211_sta_block_awake(), so retain the second
drain at the start of __cleanup_single_sta(). That drain also covers
insertion failures, which reach cleanup without setting sta->dead.
-
CVE-2026-98705
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: account proxy paths against the mesh path limit
Proxy-path churn can drive the interface path counter negative and let
later mesh path additions exceed MESH_MAX_MPATHS.
mesh_path_free_rcu() decrements the interface mpaths counter for entries
from both the mesh and proxy path tables, but mpp_path_add() never
reserves a slot in that counter. Removing or expiring a proxy path
therefore returns a slot that was never charged.
mesh_path_add() uses the same counter to enforce MESH_MAX_MPATHS, so once
it falls below the number of installed paths the limit no longer holds.
Reserve the shared quota before allocating a proxy path and release it on
every unsuccessful addition. Mesh and proxy paths now share one
1024-entry budget, so mpp_path_add() can return -ENOSPC at that limit.
-
CVE-2026-98704
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: keep fallback association elements alive
Associating to a non-transmitted MBSSID profile reads freed memory while
determining the operating channel and applying HT capabilities.
When an association response omits WMM, HT, or VHT information,
ieee80211_assoc_config_link() parses the cached BSS IEs and copies the
missing element pointers out of that fallback parse. For a
non-transmitted MBSSID profile those pointers refer to merged-profile
storage owned by the parse object, and the fallback block frees that
object at its end. The copied pointers are used afterwards to determine
the operating channel, configure bandwidth, and apply HT capabilities.
Keep the fallback parse result alive until association setup finishes.
[reorder variable declaration]
-
CVE-2026-98703
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: minstrel_ht: validate fixed rate index
The fixed_rate_idx debugfs file is a plain u32 attribute, so any value
can be written to it. minstrel_ht_update_stats() then copies the value
into mi-max_tp_rate[] and mi->max_prob_rate, and
minstrel_ht_set_rate() uses MI_RATE_GROUP()/MI_RATE_IDX() to index
minstrel_mcs_groups[] (42 entries) and mi->groups[].rates[] (10 entries)
with it.
Writing e.g. 65535 selects group 4095 and rate index 15, far outside
both arrays. The out-of-bounds entries are dereferenced and updated as
struct minstrel_rate_stats (retry counts, etc.), so the invalid index
corrupts adjacent kernel memory. With CONFIG_UBSAN_BOUNDS the access is
reported as an array-index-out-of-bounds in minstrel_ht_set_rate().
Only a valid group/rate pair, or U32_MAX to disable fixed rate
processing, can be used safely, so reject any other value when the
debugfs file is written.
The file is only reachable through a root-only debugfs mount, so this is
not a privilege boundary. The out-of-bounds access is still a bug that
must not be reachable through a writable debugfs attribute.
-
CVE-2026-98702
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: reject invalid 320 MHz CSA bandwidth
The HT/VHT channel definition validator can receive a 320 MHz
bandwidth indication from a received CSA frame on a non-6 GHz link.
It warns for this unsupported width but continues with an uninitialized
vht_operation.chan_width, which is then read by
ieee80211_chandef_vht_oper(). With panic_on_warn enabled, this lets a
received frame panic the kernel.
Reject the channel definition before entering the VHT operation
conversion. This preserves the existing CSA fallback while avoiding
both the warning and the uninitialized read.
-
CVE-2026-98701
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: release mesh path quota on failed additions
Repeated failed or duplicate mesh path additions can exhaust
MESH_MAX_MPATHS while the path table holds fewer paths, which stops new
paths to reachable destinations from being created.
mesh_path_add() reserves a slot before allocating and inserting a path.
If allocation fails, the function returns without releasing the slot. If
the rhashtable insertion reports an error or an existing destination, the
function discards its candidate but retains the reservation. No new path
is installed in any of these cases.
Release the reservation whenever the candidate is not installed.
-
CVE-2026-98700
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: set info-band for 802.3 encap offload frames
Unlike the 802.11 TX paths, ieee80211_8023_xmit() does not set
info->band from the channel context on non-MLD interfaces. It stays at
0, so ieee80211_get_tx_rates() uses the wrong band for these frames.
Set it the same way as ieee80211_build_hdr(): drop the frame if there is
no channel context, and leave the band at 0 on MLD interfaces.
-
CVE-2026-98699
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: fix mesh fast xmit path deletion UAF
mesh_fast_tx_cache() stores raw mesh_path pointers. Path deletion
flushes the cache and then frees the path with kfree_rcu(), but a
lookup that already holds the path can insert a new cache entry
after the flush. The cache then points at freed memory.
Set MESH_PATH_DELETED before flushing, and skip inserting a cache
entry if the path or MPP path is already deleted. Check this under
the cache walk lock so it is ordered with the flush. Use WRITE_ONCE()
for the deletion flag updates because the cache check reads flags
without taking state_lock.
-
CVE-2026-98698
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
wifi: mac80211: handle empty FILS association request payload
fils_encrypt_assoc_req() accepts a (Re)Association Request frame whose
last element is the FILS Session element. crypt_len is then zero and
aes_siv_encrypt() is called with an empty plaintext.
kmemdup() returns ZERO_SIZE_PTR for a zero-length allocation, so the
unconditional sg_init_one() puts an invalid page into the scatterlist.
With CONFIG_DEBUG_SG this triggers a kernel BUG in sg_set_buf();
without the debug check the bogus page is handed to the crypto backend.
AES-SIV is defined for empty plaintext and the S2V result is then the
complete output, so handle this case before the CTR step, which has
nothing to encrypt.
-
CVE-2026-98697
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
USB: serial: fix dynamic id driver deregistration race
Only free the dynamic ids after having deregistered the driver and
removed the "new_id" attribute to avoid leaking any id added by a racing
write to the attribute.
-
CVE-2026-98696
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
USB: serial: fix driver deregistration order
USB serial driver modules register one driver for the USB bus and one or
more drivers for the ports on the USB serial bus.
When unloading a driver module, the USB driver must be deregistered
before the USB serial bus drivers so that I/O is stopped before
unbinding the ports to avoid use-after-free in completion handlers
accessing port data.
Note that the "new_id" attributes must first be removed to prevent new
ids from being added and triggering a probe of the USB driver after it
has been deregistered.
-
CVE-2026-98695
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
USB: serial: fix ioctl hangup race
The tty ioctls can race with hangup and end up calling into a tty driver
for a device that is already gone or powered down.
Serialise the callbacks using the tty port mutex and add the missing
checks to make sure the port has not been hung up before accessing port
driver data or hardware.
This specifically avoids dereferencing a NULL-pointer if a device is
disconnected during lengthy break signalling.
Note that TIOCGICOUNT and TIOCMIWAIT do not access port driver data or
hardware and are therefore not affected by the race.
-
CVE-2026-98694
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Fix KASAN reported use-after-free when request is canceled
Alan reported that when doing stress testing sometimes KASAN notices
use-after-free during control channel operation (stripped down keeping
the relevant parts):
BUG: KASAN: slab-use-after-free in tb_cfg_request_sync+0x240/0x250 [thunderbolt]
Read of size 24 at addr ffff88811067f290 by task kworker/u40:2/1760
TASK
tb_cfg_request_sync+0x240/0x250 [thunderbolt]
tb_cfg_read_raw+0x367/0x510 [thunderbolt]
tb_cfg_read+0xec/0x240 [thunderbolt]
tb_port_get_link_generation+0x258/0x420 [thunderbolt]
tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt]
tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt]
tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt]
tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt]
tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt]
process_one_work+0x675/0x1230
worker_thread+0x5e6/0xf70
kthread+0x365/0x470
ret_from_fork+0x54d/0x710
ret_from_fork_asm+0x1a/0x30
Allocated by task 1760:
__kmalloc_cache_noprof+0x1ee/0x550
tb_cfg_read_raw+0x1d3/0x510 [thunderbolt]
tb_cfg_read+0xec/0x240 [thunderbolt]
tb_port_get_link_generation+0x258/0x420 [thunderbolt]
tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt]
tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt]
tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt]
tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt]
tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt]
process_one_work+0x675/0x1230
worker_thread+0x5e6/0xf70
kthread+0x365/0x470
ret_from_fork+0x54d/0x710
ret_from_fork_asm+0x1a/0x30
Freed by task 926:
kfree+0x18f/0x4a0
tb_cfg_request_put+0xb7/0xe0 [thunderbolt]
tb_cfg_request_work+0x82/0x120 [thunderbolt]
process_one_work+0x675/0x1230
worker_thread+0x5e6/0xf70
kthread+0x365/0x470
ret_from_fork+0x54d/0x710
ret_from_fork_asm+0x1a/0x30
Second to last potentially related work creation:
__queue_work+0x575/0xd00
queue_work_on+0x77/0x80
tb_cfg_request_cancel+0xc7/0x260 [thunderbolt]
tb_cfg_request_sync+0x1f6/0x250 [thunderbolt]
tb_cfg_read_raw+0x367/0x510 [thunderbolt]
tb_cfg_read+0xec/0x240 [thunderbolt]
tb_port_get_link_generation+0x258/0x420 [thunderbolt]
tb_usb3_consumed_bandwidth+0x1c1/0x2c0 [thunderbolt]
tb_tunnel_consumed_bandwidth+0xfd/0x910 [thunderbolt]
tb_available_bandwidth+0x5f2/0xeb0 [thunderbolt]
tb_recalc_estimated_bandwidth+0x2a0/0x1bc0 [thunderbolt]
tb_handle_dp_bandwidth_request+0x1897/0x5e20 [thunderbolt]
process_one_work+0x675/0x1230
worker_thread+0x5e6/0xf70
kthread+0x365/0x470
ret_from_fork+0x54d/0x710
ret_from_fork_asm+0x1a/0x30
The last stack trace is helpful because it shows that we are cancelling
a request and looking at tb_cfg_request_cancel() what might happen is
that tb_cfg_request_work() completes right before tb_cfg_request_cancel()
starts and because of this it will call schedule_work() queueing the
same work to run again. However, it is already removed from the
request_queue and reference count is dropped so when
tb_cfg_request_work() triggers again it will access memory that is
already released.
Fix this so that we first make sure a cancelled request is not handed
away from tb_cfg_request_find() or scheduled to run. Then instead of
relying on the worker to clean up the request we will do it in
tb_cfg_request_cancel() after the work is canceled from running. Make
tb_cfg_request_dequeue() release the request only if it was actually
removed from the queue.
-
CVE-2026-98693
•
published on October 18, 2026
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.
-
CVE-2026-98692
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Make the DP tunnel activation callback mandatory
tb_tunnel_alloc_dp() takes an optional callback which is run from
dprx_work once the DPRX capabilities read has completed. Without that
callback tb_dp_dprx_start() reads the capabilities synchronously and
never queues the work. It however always takes a tunnel reference which
is only dropped by dprx_work itself or by tb_dp_dprx_stop() when
cancel_delayed_work() actually canceled that work. That reference is
thus leaked for every tunnel without a callback.
The only tunnels without one are those from tb_tunnel_discover_dp(),
which are activated again when restoring from hibernation.
Pass the callback to tb_tunnel_discover_dp() as well and drop the
synchronous path such that the DPRX capabilities are always read from
dprx_work. Hibernation restore then also no longer blocks for up to 12
seconds while waiting for that read to complete.
Also fix up the KUnit tests.
-
CVE-2026-98691
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Tear down inactive DP tunnels when the domain is stopped
tb_stop() only tears down DMA tunnels so a DP tunnel that is still
waiting for dprx_work to complete keeps that work queued while the
routers are removed and the control channel is stopped. The work only
stops once the DPRX timeout has passed and because it requeues itself
until then the flush_workqueue() in tb_domain_remove() won't wait for its
final run. The callback then runs against a domain that is already torn
down. A reference to that domain is kept so the completion waiting for
that domain to disappear in unbind will block until the timeout is
eventually reached.
Tear down DP tunnels that are not active yet as well which also cancels
that work. Tunnels for displays that are already alive are untouched and
keep working.
-
CVE-2026-98690
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Fix domain reference leak when DPRX read is canceled
tb_tunnel_one_dp() takes a domain reference which is only dropped once
tb_dp_tunnel_active() has run on the work queue. If that work is
cancelled that reference is leaked. Since
commit f5cc545f5969 ("thunderbolt: Wait for tb_domain_release() to
complete when driver is removed") instead of just leaking memory this
now also blocks in the completion wait forever when unbinding the
driver.
This can be triggered whenever a DP tunnel is torn down before the DPRX
read has completed, e.g. by unplugging within the timeout, and then
unbinding the driver.
That reference only exists to keep the domain around while the DPRX work
is scheduled so let the work itself own it: take it in tb_dp_dprx_start()
and drop it in both places that end the work. Get/put are then paired
inside the same file and it doesn't matter anymore if the callback ever
runs.
-
CVE-2026-98689
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Don't access a DP tunnel after its DPRX read was canceled
tb_dp_dprx_work() checks -dprx_canceled before it takes tb->lock so it
misses a tb_dp_dprx_stop() that could not cancel the already running
work. It then polls the DPRX capabilities and runs the callback for a
tunnel that has already been torn down while the domain is suspending or
going away.
This can be hit by cancelling the DPRX read from outside the ordered
tb->wq: During suspend tb_disconnect_and_release_dp() does just this and
with a later patch tb_stop() will do it as well. The latter in combination
with the Apple NHI where the DPRX read never completed is how I hit
this.
Check the flag with tb->lock held instead and check it again in
tb_dp_tunnel_active() because the callback runs after the lock has been
dropped again.
Also clear the flag in tb_dp_dprx_start() so that it only ever describes
the work that is currently in flight.
-
CVE-2026-98688
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Fix NULL dereference in tb_remove_work()
There is a slight race between tb_remove_work() and tb_domain_remove()
which leads to dereferencing a NULL tb-root_switch pointer inside
tb_free_unplugged_xdomains():
Thread A Thread B
tb_remove_work()
tb_domain_remove()
mutex_lock(&tb->lock)
tb_stop()
/* doesn't cancel a running callback */
cancel_delayed_work(&tcm->remove_work)
...
tb_switch_remove(tb->root_switch)
tb->root_switch = NULL
mutex_unlock(&tb->lock)
mutex_lock(&tb->lock)
...
/* without checking ->root_switch */
tb_free_unplugged_xdomains(tb->root_switch)
mutex_unlock(&tb->lock)
Commit a8937f35cf39 ("thunderbolt: Remove XDomain from the bus without
holding tb->lock") doesn't seem right to move tb_free_unplugged_xdomains()
out of the &tb->lock section and the check for tb->root_switch, in
particular. It states:
For this reason separate removing the XDomain from the topology data
structures (where we need the lock) from unregistering the device from
the bus (where remove callbacks of the drivers are being called).
tb_free_unplugged_xdomains() belongs to the former group of functions
requiring the lock. And it also calls tb_xdomain_remove() which should
only be called with &tb->lock held.
Found by Linux Verification Center (linuxtesting.org) with Svace static
analysis tool.
-
CVE-2026-98687
•
published on October 18, 2026
In the Linux kernel, the following vulnerability has been resolved:
thunderbolt: Reject oversized XDomain properties responses
tb_xdp_properties_request() allocates room for 45 data dwords in its
252-byte response buffer. The XDomain length field is six bits wide,
however, and a malicious peer can set it to 63. After the fixed response
fields are subtracted, the driver treats this as 48 data dwords.
Commit 322e93448d90 ("thunderbolt: Clamp XDomain response data copy to
allocation size") only bounds the copy against data_len. If data_len is
at least 48, memcpy() reads 192 bytes from the 180-byte res-data array,
causing a 12-byte heap out-of-bounds read. Commit 4db2bd2ed478
("thunderbolt: Limit XDomain response copy to actual frame size") limits
the earlier copy but does not constrain this header-derived length.
Reject response data lengths that exceed the allocated source buffer
before copying them into the assembled property block.