| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| In the Linux kernel, the following vulnerability has been resolved:
scsi: qla2xxx: Fix use-after-free of qpair work on queue teardown
The response queue MSI-X handler qla2xxx_msix_rsp_q() schedules
qla_do_work() via queue_work(ha->wq, &qpair->q_work). qla_do_work()
dereferences the qpair (vha, rsp) and takes qpair->qp_lock.
During teardown, qla2xxx_delete_qpair() deletes the response queue, which
calls free_irq() in qla25xx_free_rsp_que(), and then frees the queue and
the qpair. free_irq() waits for running hardirq handlers but does not
cancel work already placed on ha->wq. A still-pending q_work then runs
qla_do_work() against the freed qpair and response queue, causing a
use-after-free. This is especially likely during full adapter teardown,
where destroy_workqueue(ha->wq) forces pending work to run after the queue
pairs have been freed.
Flush the work item with cancel_work_sync() in qla25xx_free_rsp_que()
after free_irq() has released the interrupt (so no new work can be
queued) and before the response queue and qpair memory are freed (so the
flushed handler still sees valid memory). Guard on rsp->qpair and ha->wq
to match the INIT_WORK() condition and avoid operating on an
uninitialized work_struct. |
| In the Linux kernel, the following vulnerability has been resolved:
scsi: qla2xxx: Skip vport under deletion in report ID acquisition
qla24xx_report_id_acquisition() format-1 handling walks ha->vp_list under
vport_slock, takes a vref_count on the matching vport and calls
qla_update_host_map() to register its port id.
A vport teardown via qla24xx_vport_delete() sets VPORT_DELETE, then
qla24xx_disable_vp() removes the vport from the host_map btree and zeroes
vha->d_id (RESET_AL_PA). The vport is only unlinked from vp_list later,
in qla24xx_deallocate_vp_id(), which clears vp_map[idx] (RESET_VP_IDX)
but does not touch host_map. In the window in between, report ID
acquisition can still find the vport on vp_list and call
qla_update_host_map(); with d_id already zeroed it takes the
btree_insert32() path and re-inserts the dying vport into host_map.
Nothing cleans that entry afterwards, so once scsi_host_put() frees the
vha a later host_map lookup dereferences freed memory.
Skip a vport that has VPORT_DELETE set before taking the reference, so it
is neither re-registered nor scheduled for DPC re-registration. This
mirrors the existing guard in qla2x00_alert_all_vps(). |
| In the Linux kernel, the following vulnerability has been resolved:
virt: acrn: Fix irqfd use-after-free during eventfd shutdown
acrn_irqfd_deassign() and the eventfd EPOLLHUP wakeup can race and free
the same struct hsm_irqfd:
CPU0 CPU1
---- ----
eventfd_release()
wake_up_poll(EPOLLHUP)
hsm_irqfd_wakeup()
queue_work(&irqfd->shutdown)
acrn_irqfd_deassign()
hsm_irqfd_shutdown()
list_del_init()
eventfd_ctx_remove_wait_queue()
eventfd_ctx_put()
kfree(irqfd)
hsm_irqfd_shutdown_work()
container_of(work, ..., shutdown)
irqfd->vm <-- use-after-free
The deassign path freed the irqfd while a shutdown work item was
already queued by EPOLLHUP (or vice versa), so the work item could
resurrect a dangling pointer through container_of().
Switch to the lifetime model used by KVM irqfds:
- Deassign/deinit only deactivate the irqfd: remove it from vm->irqfds
under irqfds_lock and queue the cleanup work.
- hsm_irqfd_shutdown_work() becomes the sole owner that unhooks the
eventfd waitqueue entry, drops the eventfd reference and frees the
irqfd.
- A new HSM_IRQFD_FLAG_SHUTDOWN bit guarded by test_and_set_bit()
ensures the cleanup work is queued at most once, no matter how many
of {EPOLLHUP, deassign, deinit} fire concurrently. This is safe to
call from the waitqueue callback, which runs with wqh->lock held and
IRQs disabled and therefore cannot take irqfds_lock.
- acrn_irqfd_deassign() flushes vm->irqfd_wq before returning so the
eventfd is fully detached on return. acrn_irqfd_deinit() deactivates
every irqfd, flushes the workqueue and only then destroys it, so no
path can queue_work() onto a torn-down workqueue.
- acrn_irqfd_assign() now installs the eventfd waitqueue entry and
publishes the irqfd to vm->irqfds under irqfds_lock, so the irqfd is
never visible to deassign/deinit before its waitqueue entry is in
place, and any EPOLLHUP that fires in the assign window queues
cleanup work that blocks on irqfds_lock until publication is done. |
| In the Linux kernel, the following vulnerability has been resolved:
perf: Fix addr_filter_ranges lifetime
Lee Jia Jie reported that since event::addr_filter_ranges is used
under RCU, it should be RCU freed. |
| In the Linux kernel, the following vulnerability has been resolved:
wifi: iwlwifi: pcie: null RX pointers after free
When iwl_pcie_tx_init() fails after RX init, nic init unwinds via
iwl_pcie_rx_free().
The freed RX members stayed non-NULL on the live transport object,
so later teardown or retry could touch stale RX state.
Set rx_pool, global_table, rxq, and alloc_page to NULL after free
to make repeated cleanup and retry paths safe. |
| In the Linux kernel, the following vulnerability has been resolved:
KEYS: trusted: Fix TPM teardown ordering
trusted_tpm_exit() drops the TPM chip reference and frees the digest
array before unregistering the trusted key type. key_type_lookup()
holds key_types_sem for reading until the key operation finishes, while
unregister_key_type() takes it for writing. It therefore provides the
synchronization point that must precede backend teardown.
The current order permits this interleaving:
CPU 0 CPU 1
trusted_tpm_exit() key_type_lookup("trusted")
put_device(&chip->dev) trusted_tpm_seal()
kfree(digests) pcrlock()
unregister_key_type() tpm_pcr_extend(..., digests)
CPU 1 can consequently dereference the freed digest array. The chip can
also be released before callbacks stop using it.
KASAN reported:
BUG: KASAN: slab-use-after-free in tpm_pcr_extend+0x1f0/0x200
Read of size 2 at addr ffff88810872d000 by task poc/89
Call Trace:
tpm_pcr_extend+0x1f0/0x200
pcrlock+0x42/0x70 [trusted]
trusted_tpm_seal+0x1b6/0x570 [trusted]
trusted_instantiate+0x293/0x340 [trusted]
__key_instantiate_and_link+0xb2/0x2b0
__key_create_or_update+0x61e/0xb50
__do_sys_add_key+0x1b8/0x310
Allocated by task 88:
__kmalloc_noprof+0x1a7/0x490
do_one_initcall+0xa1/0x390
do_init_module+0x2df/0x840
Freed by task 90:
kfree+0x131/0x3c0
trusted_tpm_exit+0x59/0xa0 [trusted]
__do_sys_delete_module+0x346/0x510
Move unregister_key_type() before releasing either resource. This stops
new lookups and waits for in-flight key operations to finish before the
backend state is destroyed. |
| In the Linux kernel, the following vulnerability has been resolved:
apparmor: fix cred UAF caused by begin_current_label_crit_section()
AppArmor's begin_current_label_crit_section() is a scary function called
from lots of LSM hooks (in particular VFS/socket-related ones) that checks
if the label referenced by the current creds is marked FLAG_STALE, and if
so, attempts to use aa_replace_current_label() to replace the creds with an
updated version that uses a new label.
The first problem with this is that it would directly lead to UAF of
`struct cred` if anything in the kernel takes a pointer to the current
creds and accesses these past a security hook invocation that replaces
creds, like so:
```
const struct cred *cred = current_cred();
alloc_file_pseudo(...);
uid_t uid = cred->euid;
```
I don't know if anything in the kernel actually does this, but I think it
is very surprising that this pattern could lead to UAF.
The second problem is that things go wrong when aa_replace_current_label()
runs with overridden credentials. aa_replace_current_label() bails out if
`current_cred() != current_real_cred()` (mirroring the check in
proc_pid_attr_write()), but this check can't actually reliably detect
overridden credentials because the overridden creds can be the same as the
objective creds.
So in approximately the following scenario, things go wrong:
1. task begins with <creds A> (as both objective and subjective creds),
with refcount=2
2. task grabs an extra reference on <creds A> for overriding
3. task calls override_creds(<creds A>), which returns a pointer to the old
subjective creds (<creds A>)
4. task enters AppArmor LSM hook
5. AppArmor checks that objective/subjective creds are equal
6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on
<creds A>
7. task leaves AppArmor LSM hook
8. task calls revert_creds(<creds A>)
9. now task->cred is <creds A> while task->real_cred is <creds B>, but the
task_struct logically holds two references to <creds B>
10. another task drops the extra reference on <creds A> that was used for
overriding, refcount drops to 0
11. now task->real_cred points to freed creds
At this point, any access to current_cred() will be UAF.
I have a test case where I run aa-disable on a profile while a process
using that profile is blocked on splice() from a FUSE passthrough file into
a full pipe; after the profile update, the pipe becomes empty, splice()
resumes, the credentials go out of sync, and a subsequent getuid() syscall
results in a KASAN UAF splat.
To fix this, instead of directly replacing creds, do it via task_work that
will run at the end of the current syscall. (The point in time at which the
cred replacement happens should have no correctness impact; it is just a
performance optimization to avoid unnecessarily touching the refcount of
the new label.)
Note that AppArmor still performs direct cred replacements in the
sb_pivotroot LSM hook after this change, and that direct cred replacements
can still happen in VFS ->write() callbacks via proc_pid_attr_write().
There are two options for what to do with aa_dup_task_ctx(): Either
explicitly reset new->label_replacement_pending after the entire
aa_task_ctx has been copied, or switch to manually copying members over.
I am switching to manually copying members over because that should make
bugs more obvious. |
| In the Linux kernel, the following vulnerability has been resolved:
serial: imx: serialize imx_uart_ports[] lifetime
imx_uart_probe() publishes its devm-allocated port in imx_uart_ports[]
before uart_add_one_port() because console setup uses the table. The entry
is not cleared when adding the port fails or after removal, leaving a
dangling pointer.
A sibling probe can register the shared console through that stale entry.
This was reproduced under KASAN on QEMU mcimx6ul-evk by unbinding a
sibling UART, unbinding the console UART and rebinding the sibling.
Keep the entry valid through uart_remove_one_port(), then clear it. Protect
port addition and removal together with their table updates so sibling
operations cannot interleave. Reject an occupied slot rather than
clobbering an active port during a duplicate-line probe. |
| In the Linux kernel, the following vulnerability has been resolved:
usb: gadget: at91_udc: drain polled-VBUS timer/work before udc is freed
In polled-VBUS mode (board.vbus_pin && board.vbus_polled), probe arms a
self-restarting cycle: at91_vbus_timer() schedules vbus_timer_work, and
at91_vbus_timer_work() calls at91_vbus_update() and re-arms the timer via
mod_timer(). Both recover the same udc through container_of and dereference
it on every iteration.
Neither teardown path cancels this cycle. udc is devm-allocated, so it is
freed after at91udc_remove() returns, and is likewise freed when probe
fails and devres runs. A timer callback or work item that is pending or
running at either point dereferences the freed udc.
Add at91_udc_shutdown_vbus_timer() and call it from at91udc_remove() and
from the usb_add_gadget_udc() failure path in probe; the remaining probe
error paths fail before the timer is armed. timer_shutdown_sync() waits
for a running callback and clears timer->function, which makes the work
handler's mod_timer() a permanent no-op; cancel_work_sync() then drains
any pending or running work whose re-arm attempt now does nothing. The
timer must be shut down first, since cancelling the work alone would let
the timer re-queue it. The guard mirrors probe: in IRQ mode the timer and
work_struct are never initialized.
This does not require a fault; a normal driver unbind can interleave with
an already queued work item.
This issue was found by an in-house static analysis tool. |
| In the Linux kernel, the following vulnerability has been resolved:
nfsd: fix fcache_disposal UAF by inlining dispose state into nfsd_net
nfsd_file_dispose_list_delayed() defers fput() to nfsd service threads
via a per-net freeme queue, preventing the shrinker and GC worker from
bearing the cost of closing files (see ffb402596147). However, the
queue lives in a separately-allocated struct nfsd_fcache_disposal that
is freed by nfsd_free_fcache_disposal_net() during per-net teardown.
The global shrinker, laundrette, and fsnotify callbacks can still be
inside nfsd_file_dispose_list_delayed() dereferencing that pointer,
causing a use-after-free.
Inline the spinlock and freeme list directly into struct nfsd_net (as
fcache_dispose_lock and fcache_dispose_list), eliminating the separately
allocated struct nfsd_fcache_disposal entirely. These fields now have
the same lifetime as the net namespace itself, so there is no dangling
pointer to chase.
nfsd_file_cache_start_net() now just initializes the inline fields and
cannot fail due to allocation. nfsd_file_cache_shutdown_net() drains
the inline list directly instead of freeing a separate struct. The
alloc/free helpers are removed. |
| In the Linux kernel, the following vulnerability has been resolved:
nfsd: fix stale s2s_cp_stateids IDR entry for async COPY
For an async COPY, nfsd4_copy() called nfs4_init_copy_state() before
dup_copy_fields(), so the s2s_cp_stateids IDR was pointed at
&u->copy->cp_stateid -- memory in the per-rqstp COMPOUND buffer that is
reused by the next request. dup_copy_fields() copies only the value into
async_copy, so the IDR slot dangled at the transient buffer for the whole
background copy. Any IDR walker then dereferences reused request memory:
the laundromat reads cs_type from it and, if the bytes look like an
expired NFS4_COPYNOTIFY_STID, follows into
refcount_dec()/idr_remove()/kfree() on garbage; manage_cpntf_state() has
the same exposure via idr_find().
Duplicate the fields first, then register the stateid on the stable
async_copy. result->cb_stateid is unchanged. |
| In the Linux kernel, the following vulnerability has been resolved:
NFSD: Prevent client use-after-free during delegation revoke
A delegation stateid holds only a bare pointer to its owning
nfs4_client and does not keep it alive. The client survives its
stateids only because __destroy_client() drains cl_delegations and
cl_revoked before free_client() runs.
nfs4_laundromat() breaks that invariant: it unhashes an
expired delegation from cl_delegations, drops deleg_lock, then
revoke_delegation() relinks it onto cl_revoked under cl_lock. In that
window the delegation is on neither list, so client_has_state() can
report no remaining state.
Every teardown path first requires cl_rpc_users to be zero, but
the laundromat holds no such reference. A client whose recalled
delegation has just timed out can therefore reach free_client()
while revoke_delegation() is still about to dereference cl_lock,
a use-after-free.
Pin the client with cl_rpc_users across the revoke so teardown blocks
until it completes, then reap the delegation from cl_revoked. A client
already expiring reaps its own, so skip it and leave the delegation on
del_recall_lru. |
| In the Linux kernel, the following vulnerability has been resolved:
HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes
mcp_i2c_smbus_read() stores the caller-supplied buffer pointer in
mcp->rxbuf for the duration of a transfer but never clears it when the
transfer finishes or times out. Once the caller frees or reuses the
buffer, mcp->rxbuf becomes a dangling pointer. A delayed or spurious
MCP2221_I2C_GET_DATA report can then drive mcp2221_raw_event() to
memcpy device data into the freed memory, causing a write
use-after-free.
Route all return paths through a single exit point that clears
mcp->rxbuf and mcp->rxbuf_size, so that the existing !mcp->rxbuf guard
in the raw_event handler can reject any report arriving after the
transfer has ended. |
| In the Linux kernel, the following vulnerability has been resolved:
ip: orphan prefetched skbs before multicast forwarding
IPv4 and IPv6 input preserve an skb->sk association installed by
bpf_sk_assign() so that local delivery can use the selected socket under
RCU. Both address families can also prefetch a socket in UDP early demux.
In both paths (BPF and UDP early demux) a reference is not guaranteed to
be held on the socket.
When a multicast packet is not locally deliverable, IPv6 hands the
original skb to ip6_mr_input(). IPv4's ip_mr_input() similarly keeps the
original skb when local delivery is not needed. Either path can put the
skb on an unresolved multicast route queue or forward it after the
receive-side RCU section ends.
After the prefetched socket is destroyed, a later skb free invokes
sock_pfree() and dereferences the stale skb->sk. Orphan the skb before
each non-local multicast forwarding path. Local delivery retains the
original skb; the existing skb_clone() calls provide multicast forwarding
with a socket-free clone. |
| In the Linux kernel, the following vulnerability has been resolved:
sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir
Normal client creation goes through rpc_setup_pipedir(), which records
clnt->pipefs_sb, but the mount-event path in __rpc_clnt_handle_event()
calls rpc_setup_pipedir_sb() directly and never refreshes that field.
The umount path also removes the directory without clearing
clnt->pipefs_sb.
After a late pipefs mount or any remount, rpc_clnt_remove_pipedir()
compares the current superblock against a stale pipefs_sb pointer and
skips cleanup, leaving pipefs dentries whose inode private data still
points at a freed rpc_clnt, leading to a potential use-after-free during
subsequent rpc_info_open() or rpc_show_info() calls.
Fix this by properly updating clnt->pipefs_sb upon mount events and
clearing it during unmount or failure paths. |
| In the Linux kernel, the following vulnerability has been resolved:
power: supply: bq24257: fix use-after-free on remove
The STAT-pin interrupt is devm-managed, so it stays armed until the devm
cleanup that runs after remove() returns. remove() cancels
bq->iilimit_setup_work while the threaded handler can still fire; that
handler reschedules the work and dereferences bq, so the work runs
against freed memory once devm frees bq.
Make the delayed work device-managed with devm_delayed_work_autocancel(),
registered before the interrupt request. The devm cleanup then releases
the interrupt first, so the handler can no longer reschedule the work,
and cancels the work before bq is freed. The explicit
cancel_delayed_work_sync() in remove() is no longer needed and is dropped.
Found by static analysis. |
| In the Linux kernel, the following vulnerability has been resolved:
power: supply: rt9455: quiesce delayed work before teardown
The threaded IRQ handler can queue pwr_rdy_work,
max_charging_time_work and batt_presence_work. pwr_rdy_work and
batt_presence_work can also queue max_charging_time_work, while
batt_presence_work can requeue itself.
rt9455_remove() cancels max_charging_time_work before
batt_presence_work. The latter can therefore queue
max_charging_time_work after it has already been cancelled:
rt9455_remove() workqueue
cancel pwr_rdy_work
cancel max_charging_time_work
batt_presence_work queues
max_charging_time_work
cancel batt_presence_work
return
devres frees rt9455_info
max_charging_time_work dereferences
rt9455_info
The IRQ also remains registered until devres cleanup and can queue more
work after any of the cancellation calls. If rt9455_hw_init() fails
after the IRQ has been requested, probe returns without cancelling work
that may already have been queued. A pending callback can then access
rt9455_info after it has been freed.
Register rt9455_cancel_all_delayed_works() through
devm_add_action_or_reset() right after devm_power_supply_register().
devres invokes the action in reverse registration order, after the
managed IRQ has been freed and before rt9455_info is released, so the
delayed works are drained in both rt9455_remove() and the probe error
path. Cancel pwr_rdy_work and batt_presence_work before
max_charging_time_work because both can queue the latter.
This issue was found by an in-house static analysis tool. |
| In the Linux kernel, the following vulnerability has been resolved:
iommu/msm: Unwind probe state on registration failure
msm_iommu_probe() adds its devm-managed IOMMU object to
qcom_iommu_devices before adding the IOMMU sysfs device and registering
it with the IOMMU core.
If iommu_device_sysfs_add() fails, probe returns with the object still on
qcom_iommu_devices. The driver core then releases the devm allocation,
leaving a dangling list entry that later list walks may dereference.
If iommu_device_register() fails, the same dangling list entry remains
and the sysfs device is left registered as well.
Unwind the sysfs device and global list entry in reverse setup order on
the corresponding failure paths. |
| In the Linux kernel, the following vulnerability has been resolved:
mmc: via-sdmmc: cancel card-detect work on remove
Disabling the device interrupt and freeing the IRQ prevents new card-detect
work from being queued, but carddet_work already queued by the handler can
still run after via_sd_remove() returns. via_sdc_card_detect() recovers the
host through container_of() and dereferences its MMIO base; once remove()
returns the host can be freed, so that work would touch freed memory.
Cancel carddet_work after freeing the IRQ and before cancelling
finish_bh_work, which the card-detect handler can also queue. carddet_work
can re-enable the interrupt through via_reset_pcictrl(); mask it again
afterwards.
This issue was found by an in-house static analysis tool and confirmed by
manual code review. |
| In the Linux kernel, the following vulnerability has been resolved:
wifi: rtl8xxxu: fix use-after-free from rx_urb_wq on stop
rtl8xxxu arms rx_urb_wq from the RX completion path:
rtl8xxxu_rx_complete() hands the URB to rtl8xxxu_queue_rx_urb(), which
queues it on rx_urb_pending_list and, once the list grows past
RTL8XXXU_RX_URB_PENDING_WATER, schedules rx_urb_wq. The worker
rtl8xxxu_rx_urb_work() drains rx_urb_pending_list, recovers priv through
container_of, and resubmits each URB through rtl8xxxu_submit_rx_urb(),
which anchors it on rx_anchor and dereferences priv->udev.
rtl8xxxu_stop() cancels the sibling work items (c2hcmd_work, ra_watchdog,
update_beacon_work) but never cancels rx_urb_wq, so a worker armed during
the last burst of RX traffic can run rtl8xxxu_rx_urb_work() after
rtl8xxxu_disconnect() has called ieee80211_free_hw(), which frees priv,
producing a use-after-free. The window opens under active RX traffic
(pending count above the watermark) followed by a disconnect.
There are two teardown races to close:
* rtl8xxxu_queue_rx_urb() decided whether to enqueue under rx_urb_lock
but called schedule_work() after dropping the lock. A completion
that observed shutdown == false and released the lock could then call
schedule_work() after rtl8xxxu_stop() had set shutdown and
cancel_work_sync() had already returned, arming the worker to run
after the teardown. Move schedule_work() under the same !shutdown
branch so the arming decision is atomic with the shutdown check.
* rtl8xxxu_rx_urb_work() anchors every URB it drained back onto
rx_anchor through rtl8xxxu_submit_rx_urb(). A worker still running
when usb_kill_anchored_urbs(&priv->rx_anchor) returned would submit a
URB that escaped the kill. In rtl8xxxu_stop(), call
cancel_work_sync(&priv->rx_urb_wq) before the kill so the worker is
drained first.
After priv->shutdown is set under rx_urb_lock, completions can no longer
queue rx_urb_wq. cancel_work_sync() then drains the last queued or running
worker, and the following usb_kill_anchored_urbs() kills the URBs it may
have submitted.
rtl8xxxu_disconnect() is covered because ieee80211_unregister_hw()
guarantees .stop() runs for a live interface before ieee80211_free_hw()
frees priv. The probe error path needs no cancel: rx_urb_wq is
INIT_WORK()'d there but cannot have been scheduled, since no URB is
submitted before ieee80211_register_hw() succeeds.
This bug was found by static analysis. |