| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix use-after-free on reloc root after error in insert_dirty_subvol()
If during relocation we fail in insert_dirty_subvol() because
btrfs_update_reloc_root() returned an error, we will leave a root's
reloc_root field pointing to a reloc root that was freed instead of NULL,
resulting later in a use-after-free, or double free attempt during
unmount.
The sequence of steps is this:
1) During relocation the call to btrfs_update_reloc_root() in
insert_dirty_subvol() fails, so insert_dirty_subvol() returns the
error to merge_reloc_root() without adding the root to the list
rc->dirty_subvol_roots;
2) Then merge_reloc_root() aborts the current transaction because
insert_dirty_subvol() returned an error;
3) Up the call chain, merge_reloc_roots() gets the error, adds the
reloc root for root X to the local reloc_roots list and jumps to the
'out' label, where it calls free_reloc_roots() to free all the reloc
roots in the local reloc_roots list. This frees the reloc root for
root X;
4) We go up the call chain to relocate_block_group() which calls
clean_dirty_subvols() to go over dirty roots and set their
->reloc_root field to NULL, but root X is not in the dirty_subvol_roots
list, so its ->reloc_root still points to a reloc root;
5) Relocation finishes, with an error and a transaction abort, but the
->reloc_root field for root X still points to the reloc root that was
freed in step 3;
6) When unmounting the fs we end up calling:
btrfs_free_fs_roots()
btrfs_drop_and_free_fs_root()
--> calls btrfs_put_root() against root X's ->reloc_root
which is not NULL and points to the already freed
reloc root in step 4 above
Resulting in a use-after-free to a double free attempt.
Syzbot reported this with the following dmesg/syslog:
[ 106.004389][ T5339] BTRFS error (device loop0 state A): Transaction aborted (error -5)
[ 106.014266][ T5339] BTRFS: error (device loop0 state A) in merge_reloc_root:1655: errno=-5 IO failure
[ 106.021891][ T1061] BTRFS error (device loop0 state A): error while writing out transaction: -5
[ 106.026964][ T1061] BTRFS warning (device loop0 state A): Skipping commit of aborted transaction.
[ 106.033807][ T5340] BTRFS error (device loop0 state A): bdev /dev/loop0 errs: wr 3, rd 0, flush 0, corrupt 0, gen 0
[ 106.039265][ T1061] BTRFS: error (device loop0 state A) in cleanup_transaction:2067: errno=-5 IO failure
[ 106.044382][ T5339] BTRFS info (device loop0 state EA): forced readonly
[ 106.074329][ T5339] BTRFS: error (device loop0 state EA) in merge_reloc_roots:1887: errno=-5 IO failure
[ 106.081004][ T5356] BTRFS info (device loop0 state EA): scrub: started on devid 1
[ 106.085611][ T5339] BTRFS info (device loop0 state EA): balance: ended with status: -30
[ 106.089517][ T5356] BTRFS info (device loop0 state EA): scrub: not finished on devid 1 with status: -30
[ 106.662365][ T5338] BTRFS info (device loop0 state EA): last unmount of filesystem 3a375e4e-b156-4d76-a2ad-16e198ce1409
[ 106.682946][ T5338] ==================================================================
[ 106.686574][ T5338] BUG: KASAN: slab-use-after-free in btrfs_put_root+0x2f/0x250
[ 106.690090][ T5338] Write of size 4 at addr ffff88803f978630 by task syz.0.0/5338
[ 106.693173][ T5338]
[ 106.694279][ T5338] CPU: 0 UID: 0 PID: 5338 Comm: syz.0.0 Not tainted syzkaller #0 PREEMPT(full)
[ 106.694293][ T5338] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 106.694300][ T5338] Call Trace:
[ 106.694308][ T5338] <TASK>
[ 106.694314][ T5338] dump_stack_lvl+0xe8/0x150
[ 106.694331][ T5338] print_address_description+0x55/0x1e0
[ 106.694343][ T5338] ? btrfs_put_root+0x2f/0x250
[ 106.694358][ T5338] print_report+0x58/0x70
[ 106.
---truncated--- |
| In the Linux kernel, the following vulnerability has been resolved:
vhost-scsi: flush backend after device ioctls
vhost-scsi translates guest response descriptors into userspace iovecs
when commands are submitted. Target-core completes those commands
asynchronously, so VHOST_SET_MEM_TABLE can replace the memory table while
an in-flight command still retains response iovecs translated through the
old table.
If the old mapping is reused after VHOST_SET_MEM_TABLE returns, command
completion can write the response to an unrelated userspace object.
Flush the vhost-scsi backend after vhost_dev_ioctl() handles a device
ioctl. This waits for in-flight commands that can still use the old
response iovecs before the ioctl returns. |
| In the Linux kernel, the following vulnerability has been resolved:
usb: dwc3: gadget: Fix use-after-free in dwc3_gadget_free_endpoints due to race condition
In dwc3_gadget_init_endpoint, &dep->nostream_work is bound with
dwc3_nostream_work, and dwc3_gadget_endpoint_stream_event can queue
this delayed work on system_percpu_wq when a DEPEVT_STREAM_NOSTREAM
event is received.
If we remove the gadget, dwc3_gadget_free_endpoints makes cleanup and
the memory allocated for dep with kzalloc() is released by kfree(dep),
while the delayed work mentioned above may still be pending or
running. The sequence of operations that may lead to a UAF bug is as
follows:
CPU0 CPU1
| dwc3_thread_interrupt
| dwc3_endpoint_interrupt
| dwc3_gadget_endpoint_stream_event
| queue_delayed_work(system_percpu_wq,
| &dep->nostream_work)
dwc3_gadget_free_endpoints |
dwc3_free_trb_pool(dep) |
list_del(&dep->endpoint.ep_list) |
dwc3_debugfs_remove_endpoint_dir(dep) |
kfree(dep) |
// dep is freed |
| dwc3_nostream_work
| // use dep (use-after-free)
Fix it by canceling the delayed work before kfree(dep) in
dwc3_gadget_free_endpoints. |
| In the Linux kernel, the following vulnerability has been resolved:
iommufd: Fix UAF in selftest IOPF reporting
IOMMUFD selftest TRIGGER_IOPF borrows an attach handle from
group->pasid_array without synchronizing against PASID detach,
then a concurrent iommu_report_device_fault() can dereference
that borrowed handle's domain pointer after the detach erases
the handle and frees the backing struct iommufd_attach_handle.
TRIGGER_IOPF then dereferences the freed handle, causing a UAF.
Fix by adding a iopf_rwsem in mock_dev to follow the expected design
of a real driver. Hold its read side across the whole
iommu_report_device_fault() call, and its write side around every
path that attaches, detaches, or replaces a device domain.
This can block new reports and drains in-flight reports before an old
attach handle or the IOPF fault parameter can be removed.
Also take the write side while registering a mock device, since
it can invoke the mock driver's default-domain attach callback. |
| In the Linux kernel, the following vulnerability has been resolved:
ipv4: fib: Don't dump dying fib_info in fib_leaf_notify().
syzbot reported use-after-free in nsim_fib4_prepare_event(). [0]
The problem is that the following functions call fib_info_hold() /
refcount_inc() while dumping fib_info under RCU, which is unsafe.
* mlxsw_sp_router_fib4_event()
* rocker_router_fib_event()
* nsim_fib4_prepare_event()
refcount_inc_not_zero() must be used, but it would be too late
there.
Let's guarantee the lifetime of fib_info in fib_leaf_notify().
Note that IPv6 does not need the corresponding change since
fib6_table_dump() holds fib6_table.tb6_lock.
[0]:
refcount_t: addition on 0; use-after-free.
WARNING: lib/refcount.c:25 at refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25, CPU#0: kworker/u8:15/3420
Modules linked in:
CPU: 0 UID: 0 PID: 3420 Comm: kworker/u8:15 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026
Workqueue: netns cleanup_net
RIP: 0010:refcount_warn_saturate+0x9f/0x110 lib/refcount.c:25
Code: eb 66 85 db 74 3e 83 fb 01 75 4c e8 1b f1 22 fd 48 8d 3d 84 cb f1 0a 67 48 0f b9 3a eb 4a e8 08 f1 22 fd 48 8d 3d 81 cb f1 0a <67> 48 0f b9 3a eb 37 e8 f5 f0 22 fd 48 8d 3d 7e cb f1 0a 67 48 0f
RSP: 0018:ffffc9000f2c7270 EFLAGS: 00010293
RAX: ffffffff84a18858 RBX: 0000000000000002 RCX: ffff888032ff9ec0
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff8f9353e0
RBP: 0000000000000000 R08: ffff888032ff9ec0 R09: 0000000000000005
R10: 0000000000000100 R11: 0000000000000004 R12: ffff8880570cc000
R13: dffffc0000000000 R14: ffff88802b40563c R15: ffff8880570cc000
FS: 0000000000000000(0000) GS:ffff888126173000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fb1f4d5d000 CR3: 000000006072a000 CR4: 00000000003526f0
Call Trace:
<TASK>
__refcount_add include/linux/refcount.h:-1 [inline]
__refcount_inc include/linux/refcount.h:366 [inline]
refcount_inc include/linux/refcount.h:383 [inline]
fib_info_hold include/net/ip_fib.h:629 [inline]
nsim_fib4_prepare_event drivers/net/netdevsim/fib.c:930 [inline]
nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1000 [inline]
nsim_fib_event_nb+0x1055/0x1240 drivers/net/netdevsim/fib.c:1043
call_fib_notifier+0x45/0x80 net/core/fib_notifier.c:25
call_fib_entry_notifier net/ipv4/fib_trie.c:90 [inline]
fib_leaf_notify net/ipv4/fib_trie.c:2176 [inline]
fib_table_notify net/ipv4/fib_trie.c:2194 [inline]
fib_notify+0x36b/0x5e0 net/ipv4/fib_trie.c:2217
fib_net_dump net/core/fib_notifier.c:70 [inline]
register_fib_notifier+0x184/0x360 net/core/fib_notifier.c:108
nsim_fib_create+0x85d/0x9f0 drivers/net/netdevsim/fib.c:1596
nsim_dev_reload_create drivers/net/netdevsim/dev.c:1604 [inline]
nsim_dev_reload_up+0x374/0x7c0 drivers/net/netdevsim/dev.c:1058
devlink_reload+0x501/0x8d0 net/devlink/dev.c:475
devlink_pernet_pre_exit+0x1ff/0x420 net/devlink/core.c:558
ops_pre_exit_list net/core/net_namespace.c:161 [inline]
ops_undo_list+0x187/0x940 net/core/net_namespace.c:234
cleanup_net+0x56e/0x800 net/core/net_namespace.c:702
process_one_work kernel/workqueue.c:3314 [inline]
process_scheduled_works+0xb5d/0x1860 kernel/workqueue.c:3397
worker_thread+0xa53/0xfc0 kernel/workqueue.c:3478
kthread+0x388/0x470 kernel/kthread.c:436
ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK> |
| In the Linux kernel, the following vulnerability has been resolved:
xfrm: Fix dev use-after-free in xfrm async resumption
xfrm async resumption hold skb->dev refcnt until after transport_finish.
However, xfrm_rcv_cb may modify skb->dev to tunnel dev without taking
device reference, such as vti_rcv_cb. The subsequent async resumption
will decrement the tunnel device's reference count, which lead to uaf
of tunnel dev and refcnt leak of orig dev as below:
unregister_netdevice: waiting for vti1 to become free. Usage count = -2
Stash the original skb->dev to fix refcnt imbalance. The new skb->dev set
by xfrm_rcv_cb can race with device teardown. Extend rcu protection over
xfrm_rcv_cb and transport_finish to prevent races. |
| In the Linux kernel, the following vulnerability has been resolved:
KVM: x86: Fix shadow paging use-after-free due to unexpected role
Commit 0cb2af2ea66ad ("KVM: x86: Fix shadow paging use-after-free due
to unexpected GFN") fixed a shadow paging mismatch between stored and
computed GFNs; the bug could be triggered by changing a PDE mapping from
outside the guest, and then deleting a memslot. The rmap_remove()
call would miss entries created after the PDE change because the GFN
of the leaf SPTE does not match the GFN of the struct kvm_mmu_page.
A similar hole however remains if the modified PDE points to a non-leaf
page. In this case the gfn can be made to match, but the role does not
match: the original large 2MB page creates a kvm_mmu_page with direct=1,
while the new 4KB needs a kvm_mmu_page with direct=0. However,
kvm_mmu_get_child_sp() does not compare the role, and therefore reuses
the page.
The next step is installing a leaf (4KB) SPTE on the new path which
records an rmap entry under the gfn resolved by the walk. But when
that child is zapped its parent kvm_mmu_page has direct=1 and
kvm_mmu_page_get_gfn() computes the gfn for the 4KB page as
sp->gfn + index instead of using sp->shadowed_translation[] (or sp->gfns[]
in older kernels). It therefore fails to remove the recorded entry.
When the memslot is dropped the shadow page is freed but the rmap
entry survives, as in the scenario that was already fixed. Code that
later walks that gfn (dirty logging, MMU notifier invalidation, and
so on) dereferences an sptep that lies in the freed page, causing the
use-after-free. |
| In the Linux kernel, the following vulnerability has been resolved:
eventpoll: fix ep_remove struct eventpoll / struct file UAF
ep_remove() (via ep_remove_file()) cleared file->f_ep under
file->f_lock but then kept using @file inside the critical section
(is_file_epoll(), hlist_del_rcu() through the head, spin_unlock).
A concurrent __fput() taking the eventpoll_release() fastpath in
that window observed the transient NULL, skipped
eventpoll_release_file() and ran to f_op->release / file_free().
For the epoll-watches-epoll case, f_op->release is
ep_eventpoll_release() -> ep_clear_and_put() -> ep_free(), which
kfree()s the watched struct eventpoll. Its embedded ->refs
hlist_head is exactly where epi->fllink.pprev points, so the
subsequent hlist_del_rcu()'s "*pprev = next" scribbles into freed
kmalloc-192 memory.
In addition, struct file is SLAB_TYPESAFE_BY_RCU, so the slot
backing @file could be recycled by alloc_empty_file() --
reinitializing f_lock and f_ep -- while ep_remove() is still
nominally inside that lock. The upshot is an attacker-controllable
kmem_cache_free() against the wrong slab cache.
Pin @file via epi_fget() at the top of ep_remove() and gate the
critical section on the pin succeeding. With the pin held @file
cannot reach refcount zero, which holds __fput() off and
transitively keeps the watched struct eventpoll alive across the
hlist_del_rcu() and the f_lock use, closing both UAFs.
If the pin fails @file has already reached refcount zero and its
__fput() is in flight. Because we bailed before clearing f_ep,
that path takes the eventpoll_release() slow path into
eventpoll_release_file() and blocks on ep->mtx until the waiter
side's ep_clear_and_put() drops it. The bailed epi's share of
ep->refcount stays intact, so the trailing ep_refcount_dec_and_test()
in ep_clear_and_put() cannot free the eventpoll out from under
eventpoll_release_file(); the orphaned epi is then cleaned up
there.
A successful pin also proves we are not racing
eventpoll_release_file() on this epi, so drop the now-redundant
re-check of epi->dying under f_lock. The cheap lockless
READ_ONCE(epi->dying) fast-path bailout stays. |
| In the Linux kernel, the following vulnerability has been resolved:
accel/rocket: fix UAF via dangling GEM handle in create_bo
rocket_ioctl_create_bo() inserts a GEM handle into the file's IDR via
drm_gem_handle_create() early on, then performs several operations that
can fail (sgt allocation, drm_mm insert, iommu_map). If any fail after
the handle is live, the error path calls drm_gem_shmem_object_free()
which kfree's the object without removing the handle from the IDR.
This leaves a dangling handle pointing to freed slab memory. Any
subsequent ioctl using that handle (PREP_BO, FINI_BO, SUBMIT) calls
drm_gem_object_lookup() and dereferences freed memory (UAF).
Fix by moving drm_gem_handle_create() to after all fallible operations
succeed, matching the pattern used by panfrost, lima, and etnaviv.
Also fix drm_mm_insert_node_generic() whose return value was silently
overwritten by iommu_map_sgtable() on the next line. Add the missing
error check.
[tomeu: Move handle creation to the very end] |
| Use after free in DevTools in Google Chrome prior to 154.0.8037.57 allowed a remote attacker leveraging social engineering to execute arbitrary code inside the sandbox via a crafted HTML page. (Chromium security severity: High) |
| In the Linux kernel, the following vulnerability has been resolved:
SUNRPC: Zero rpc_gss_wire_cred at svcauth_gss_decode_credbody() entry
svcauth_gss_decode_credbody() writes the caller's
rpc_gss_wire_cred field by field and assigns gc_ctx.len only on
the success tail. The caller storage is svcdata->clcred, which
lives in the per-svc_rqst gss_svc_data and is reused across
requests. Early decode failures leave partially decoded state
mixed with residue from the prior request.
The trailing body_len tightness check is the sharpest case:
xdr_stream_decode_opaque_inline() has already written gc_ctx.data
with a borrowed inline pointer into the current request's XDR
pages, but gc_ctx.len retains its prior value. Once the request
pages are released the pooled clcred carries a dangling pointer
paired with a stale length.
Zero the caller's rpc_gss_wire_cred at function entry so that
every early-return path leaves a deterministic all-zero cred.
On the trailing tightness-check path, gc_ctx.len is now zero
instead of stale, which neuters length-driven consumers such as
gss_svc_searchbyctx() that would otherwise walk the dangling
data pointer. |
| A flaw was found in GCC. When an application calls the erase_if function on a binary heap priority queue in libstdc++, the library reallocates storage but fails to update its internal entry pointer. An attacker capable of triggering this operation can exploit this use-after-free condition, leading to a Denial of Service (DoS) via an application crash or potential memory corruption. |
| A use-after-free vulnerability was found in libxslt while parsing xsl nodes that may lead to the dereference of expired pointers and application crash. |
| In the Linux kernel, the following vulnerability has been resolved:
RDMA/core: Fix potential use after free in uverbs_free_dmah()
When accessing a dmah via the netlink path the only synchronization
mechanism for the said dmah is rdma_restrack_get().
Currently, rdma_restrack_del() is invoked at the end of
uverbs_free_dmah(), which is too late, since by that point
vendor-specific resources associated with the dmah might already be
freed. This can leave a short window where the dmah remains accessible
through restrack, leading to a potential use-after-free.
Fix this by moving the rdma_restrack_begin_del() call to the start of
uverbs_free_dmah(), ensuring that the dmah is removed from restrack
before its internal resources are released. This guarantees that no new
users hold references to a dmah that is in the process of destruction.
In addition, this change preserves the intended inverted order
between create and destroy routines: resources are added to
restrack at the end of successful creation, and hence shall be removed
from the restrack first thing during the destruction flow, which keeps
the lifecycle management consistent and predictable. |
| In the Linux kernel, the following vulnerability has been resolved:
i3c: master: Fix device_register() error path
When device_register() fails in i3c_master_register_new_i3c_devs(),
put_device() is called to drop the reference taken by
device_register(). That drops the last reference, so the device's
release callback i3c_device_release() runs and frees the i3c_device.
Two problems follow from that:
i3c_device_release() does WARN_ON(i3cdev->desc), so it warns because
desc->dev->desc still points back at the descriptor. Clear it before
calling put_device().
After put_device() frees the i3c_device, desc->dev is left pointing at
freed memory, so clear desc->dev as well. That prevents, for example,
i3c_master_unregister_i3c_devs() seeing desc->dev as non-NULL and
dereferencing it. |
| In the Linux kernel, the following vulnerability has been resolved:
drm/amdgpu: flush pending RCU callbacks on module unload
Call rcu_barrier() in module exit to wait for outstanding call_rcu() callbacks
before freeing module text, preventing late callback execution in freed memory.
BUG: unable to handle page fault for address: ffffffffc1d59c40
PGD 6a12067 P4D 6a12067 PUD 6a14067 PMD 13698b067 PTE 0
Oops: 0010 [#1] SMP NOPTI
RIP: 0010:0xffffffffc1d59c40
Code: Unable to access opcode bytes at RIP 0xffffffffc1d59c16.
RSP: 0018:ffffc900198c0f28 EFLAGS: 00010286
RAX: ffffffffc1d59c40 RBX: ffff897c7d6b61c0 RCX: ffff88826aff4590
RDX: ffff8884d8b35490 RSI: ffffc900198c0f30 RDI: ffff88812af67290
RBP: 000000000000000a (DONE segment entries) R08: 0000000000000000 R09: 0000000000000100
R10: 0000000000000000 R11: ffffffff82a06100 R12: ffff88811a4e3700
R13: 0000000000000000 R14: ffff897c7d6b6270 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff897c7d680000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffc1d59c16 CR3: 00000104a980a001 CR4: 0000000002770ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<IRQ>
? rcu_do_batch+0x163/0x450
? rcu_core+0x177/0x1c0
? __do_softirq+0xc1/0x280
? asm_call_irq_on_stack+0xf/0x20
</IRQ>
? do_softirq_own_stack+0x37/0x50
? irq_exit_rcu+0xc4/0x100
? sysvec_apic_timer_interrupt+0x36/0x80
? asm_sysvec_apic_timer_interrupt+0x12/0x20
? cpuidle_enter_state+0xd4/0x360
? cpuidle_enter+0x29/0x40
? cpuidle_idle_call+0x108/0x1a0
? do_idle+0x77/0xf0
? cpu_startup_entry+0x19/0x20
? secondary_startup_64_no_verify+0xbf/0xcb
(cherry picked from commit feaa5039f6c12acc9aa934c2d45dcd251a12c69f) |
| In the Linux kernel, the following vulnerability has been resolved:
staging: octeon: add missing napi_disable in cvm_oct_rx_shutdown
cvm_oct_rx_shutdown calls free_irq and netif_napi_del without
disabling the napi instance first. As the free_irq only waits
for completion of hard interrupt handlers, the napi poll
function could still be active. If cvm_oct_remove proceeds to
free the plat structure (which holds the NAPI instances), the
active poll function will access freed memory, resulting in a
use-after-free crash. |
| In the Linux kernel, the following vulnerability has been resolved:
wifi: iwlwifi: mld: purge async notifications upon nic error
This fixes a kernel panic in reconfig failure:
1. we have a BSS connection
2. we have a NAN connection
3. FW error occurs
4. reconfig restores the BSS connection
5. however, restoring the NAN connection fails due to a FW error.
6. erroneously, ieee80211_handle_reconfig_failure is called and marks all
interfaces as not-in-driver (will be fixed in a different patch).
7. mac80211 frees the links of the BSS connection but doesn't tell the
driver about that, as it thinks that this vif is not in the driver.
8. in ieee80211_stop_device, *ALL* wiphy works are getting flushed
(erroneously?)
9. Therefore, async_handlers_wk is being executed, processing the
statistics notification that was received after we restored the BSS
connection.
10. the notification handler dereferences fw_id_to_bss_conf[id], which is
now a dangling pointer, as mac80211 already freed this link in (7).
11. On the first access to one of the links fields, we panic.
While this can and should be fixed by removing the call to
ieee80211_handle_reconfig_failure in (6), it is also not a good idea to
carry and maybe handle notifications from a dead FW.
We do purge the notifications when we stop the FW, but in reconfig
failure we stop the FW too late, after the notifications are processed.
In addition, async_handlers_wk can always be scheduled before the
reconfig work.
Purge the notifications immediately when transport notifies about a nic
error. |
| PDFio before 1.6.5 contains a dangling pointer vulnerability in the dictionary string-formatting function that stores a pointer to a stack-local buffer in the document dictionary without copying the string value. In multi-threaded or pooled-request environments, attackers or concurrent users can trigger stack memory reuse across requests, causing cross-tenant document content corruption by silently overwriting one caller's dictionary string values with another caller's data. |
| In the Linux kernel, the following vulnerability has been resolved:
x86/mm/pat: Acquire init_mm read lock on attribute changes to avoid UAF
A previous commit protected against races between ptdump and CPA collapse,
however one still exists between attribute changes and collapse as reported
by Denis V. Lunev (linked).
When an attribute change arises, a lockless page table walker obtains a PTE
entry, which is later written to via set_pte_atomic():
...
-> change_page_attr_set_clr()
-> __change_page_attr_set_clr()
-> __change_page_attr()
-> _lookup_address_cpa()
-> lookup_address_in_pgd_attr()
-> [ lockless page table walker ]
-> set_pte_atomic()
There is nothing preventing a concurrent CPA collapse which can free the
PTE that was retrieved here, resulting in a use-after-free.
With the mmap write lock taken on init_mm over CPA collapse, resolve this
race by acquiring an mmap read lock on init_mm over
__change_page_attr_set_clr().
This locks across the whole operation over which the walk and the PTE
entry write occurs, solving the race.
It is safe to do this here, as no spinlocks are held upon entry to
__change_page_attr_set_clr().
However, the lock must not be held over an allocation, as allocation can
trigger reclaim and shrinkers may call into CPA recursively, making
deadlocks possible (init_mm -> ... -> fs_reclaim -> init_mm).
A page table is allocated when a huge page needs to be split:
-> change_page_attr_set_clr()
-> __change_page_attr_set_clr()
-> __change_page_attr()
-> split_large_page()
[ pagetable_alloc() ]
-> __split_large_page()
Avoid deadlocks by dropping the mmap lock across pagetable_alloc() in
split_large_page() and track whether this is needed by adding a new
'init_mm_read_locked' flag to struct cpa_data.
This is safe as __split_large_page() (called with locks re-established)
revalidates that the page table entry is the same as it was prior to the
locks being dropped and __change_page_attr() repeats the entire page table
walk whenever a split occurs, so concurrent split and collapse are
accounted for.
Concurrent ptdump is also safe as the lock is only dropped over page table
allocation during which time the page table has not yet been modified.
The CPA_COLLAPSE flag is only set by set_memory_rox(), which exclusively
operates upon vmalloc ranges, and on x86 only within the module mapping
space.
This is important, because some callers directly invoke
__change_page_attr_set_clr(), bypassing this lock. However, none of these
operate within the module mapping space.
* cpa_process_alias() - a recursive helper called by
__change_page_attr_set_clr().
* __set_memory_enc_pgtable() - operates on the direct mapping and (via
__vmbus_establish_gpadl()) the vmalloc mapping space.
* __set_pages_[n]p() - called by set_direct_map_[invalid, default,
valid]_noflush(), __kernel_map_pages() - operates on the direct map.
* kernel_[un]map_pages_in_pgd() - operates on EFI ranges.
This work is based upon Denis V. Lunev's excellent analysis of the bug
with gratitude.
[ dhansen: move to imperative voice in changelog ] |