In the Linux kernel, the following vulnerability has been resolved:
ASoC: SOF: sof-audio: Fix error path in sofwidgetsetupunlocked()
If either tplgops->daiconfig or widgetkcontrolsetup fail during widget setup we would double decrement the usecount of the widget because the sofwidgetfreeunlocked() would be called twice, similarly the coreput would be invoked twice as well.
Since the usecount and coreput() is handled within the widgetfree function we need to return without falling through the pipewidgetfree label.
The fixes tag is picked to the last change around this part of the code which is adequately old enough for backporting purposes.
In the Linux kernel, the following vulnerability has been resolved:
drm/amdgpu: Fix UVD dpb min size calculation for H264
This should use actual number of references from the decode message, instead of maximum derived from level.
(cherry picked from commit 64b525edb7e7bdfcdc77883c5e413804e2396856)
In the Linux kernel, the following vulnerability has been resolved:
dmaengine: sun6i-dma: Fix reclaim descriptors while terminating DMA
When terminating DMA transfers, active descriptors are not properly reclaimed. Only cyclic descriptors were handled, leaving non-cyclic descriptors and their LLI chains to be permanently leaked.
Fix by using vchanterminatevdesc() which handles both cyclic and non-cyclic descriptors by adding them to descterminated queue for proper cleanup.
Add pchan->desc != pchan->done check to prevent double-adding completed descriptors, which would corrupt the list.
In the Linux kernel, the following vulnerability has been resolved:
ipvs: fix the checksum validations
ipvsinicmpv6() is missing checksum validation for ICMPv6 packets from clients. In fact, as for TCP/UDP we should validate the checksum for ICMP packets only when we mangle the packets on MASQ or on reply for tunnel.
Also, Sashiko points out that handleresponseicmp() being common for IPv4 and IPv6 is missing the pseudo-header calculation while validating ICMPv6 messages from real servers which is a problem if checksum is not validated by the hardware.
Fix the problems by creating ipvschecksumcommoncheck() helper and use it for TCP/UDP/ICMP both for IPv4 and IPv6. Rely on the nfchecksum() for validating the ICMP messages but use it also for TCP and UDP.
Use correct IP offset for IPVSDBGRLPKT for TCP/UDP/SCTP.
IPVS packets (TCP/UDP/SCTP/ICMP) do not need checksum validation on LOCALOUT (local clients or local real servers) and on FORWARD (traffic from servers on LAN). Do it only on LOCALIN, in case nfchecksum() is not called on PREROUTING.
Also, ipvschecksumcomplete() can be marked static.
In the Linux kernel, the following vulnerability has been resolved:
erofs: remove fscache backend entirely
EROFS over fscache was introduced to provide image lazy pulling functionality. After the feature landed, the fscache subsystem made netfs a new hard dependency, which is unexpected for a local filesystem and has an kernel-defined caching hierarchy which could be inflexible compared to the fanotify pre-content hooks. Therefore, this feature has been deprecated for almost two years.
As EROFS file-backed mounts and fanotify pre-content hooks both upstream for a while and already providing equivalent functionality (erofs-utils has supported fanotify pre-content hooks), let's remove the fscache backend now.
The main application of this feature is Nydus [1], and they plan to move to use fanotify pre-content hooks in the near future too.
I hope this patch can be merged into Linux 7.2, which is also motivated by newly found implementation issues [2][3] that are not worth investigating given the deprecation and limited development resources. The associated fscache/cachefiles cleanup patch will follow separately through the vfs tree (netfs) later: it seems fine since the codebase is isolated by CONFIGCACHEFILESONDEMAND.
[1] https://github.com/dragonflyoss/nydus/blob/v2.1.0/docs/nydus-fscache.md [2] https://github.com/dragonflyoss/nydus/pull/1824 [3] https://lore.kernel.org/r/20260619135800.1594811-1-michael.bommarito@gmail.com
In the Linux kernel, the following vulnerability has been resolved:
netfs: clear PGprivate2 on copy-to-cache append failure
netfspgpriv2copytocache() marks the folio with PGprivate2 before netfspgpriv2copyfolio() appends it to the copy-to-cache rolling buffer.
If the append fails, the folio is not queued for cache writeback, so the PGprivate2 state and its reference must be released immediately.
In the Linux kernel, the following vulnerability has been resolved:
iommufd: Fix wrong hwpt passed to iommufdautoresponsefaults on replace
iommufdhwptreplacedevice() calls:
iommufdautoresponsefaults(hwpt, oldhandle);
passing the new hwpt together with the handle of the device's old domain. This should be a parameter mismatch:
1. Semantically, iommufdautoresponsefaults(x, handle) scans x->fault's deliver list and response xarray for groups matching "handle". A group is queued under the hwpt that was attached at fault-delivery time. oldhandle is fetched before the domain switch, so its group lives on old->fault, not on the new hwpt->fault.
2. Historically, the first argument was "old". The routine was introduced by commit b7d8833677ba ("iommufd: Fault-capable hwpt attach/detach/replace") as faultdomainreplacedev() in fault.c, correctly calling iommufdautoresponsefaults(old, curr). Commit fb21b1568ada ("iommufd: Make attachhandle generic than fault specific") moved this into iommufdhwptreplacedevice() in device.c and swapped it to "hwpt". This should be a refactor regression, not an intentional change.
Fix this by passing "old" instead.
In the Linux kernel, the following vulnerability has been resolved:
mshv: Order ptvparray publish against irqfd assertion path
mshvpartitionioctlcreatevp() initialises a VP struct (allocations, mutexinit, initwaitqueuehead, page mappings) and then publishes the pointer into partition->ptvparray. Several ISR paths read this array locklessly: the intercept ISR, the two scheduler ISRs, and mshvtryassertirqfast() on the irqfd fast path.
Of these, only mshvtryassertirqfast() can structurally race the publish. It runs from an eventfd waker without holding ptmutex, and MSHVIRQFD does not require the target lapicapicid (== vpindex) to refer to an existing VP at registration time. A user can therefore register an irqfd targeting a yet-to-be-created VP, then trigger mshvtryassertirqfast() concurrently with MSHVCREATEVP for the same index. On weakly-ordered architectures the reader can observe a non-NULL pointer in ptvparray before the initialising stores to the VP struct become visible, leading to use of partially-initialised fields (e.g. vpregisterpage).
The other ISR readers cannot reach this race: the hypervisor will not generate intercept or scheduler messages for a VP that has never been told to run, and the user can only call MSHVRUNVP on the VP fd returned by MSHVCREATEVP, which by construction is returned after the publish. Leave those readers as plain loads.
Use smpstorerelease() in mshvpartitionioctlcreatevp() to publish the pointer, and pair it with smploadacquire() in mshvtryassertirqfast(). On x86 these compile to plain accesses under TSO; on ARM64 they emit one-instruction acquire/release barriers, acceptable on this fast path.
The destroy-side path (destroypartition() clearing ptvparray[i] to NULL after kfree(vp)) has a separate ordering and lifetime concern that is out of scope here.
In the Linux kernel, the following vulnerability has been resolved:
erofs: cap LZMA stream pool size
fs/erofs/decompressorlzma.c sizes the module-global MicroLZMA stream pool from numpossiblecpus() when the lzmastreams module parameter is unset, then zerofsloadlzmaconfig() preallocates one image-supplied dictionary per stream, accepting dictionaries up to 8 MiB. On high-CPU systems, a small EROFS image can pin hundreds of MiB of vmalloc-backed decoder state until the erofs module is unloaded.
Impact: An EROFS image mounted by the system can pin up to 8 MiB of vmalloc memory per LZMA stream, either as intended or unexpectedly.
Bound the default stream count by a new CONFIGEROFSFSZIPLZMADEFAULTMAXSTREAMS option, default 16, so the worst-case default preallocation is 128 MiB if the number of CPUs is no less than 16 while preserving the existing per-image dictionary limit. An explicit lzmastreams module parameter is still honoured as-is, so administrators who deliberately size the pool are not affected.
In the Linux kernel, the following vulnerability has been resolved:
drm/vmwgfx: use checkaddoverflow for shader size+offset bound
vmwshaderdefine() validates the user-supplied shader window against its backing buffer with
(u64)buffer->tbo.base.size < (u64)size + (u64)offset
drmvmwshadercreatearg::offset is u64 in the uapi; when it is near U64MAX the unsigned addition wraps and the resulting tiny value passes the check. The unbounded offset is then stored in res->guestmemoryoffset and forwarded to host SVGA shader-create commands.
Use checkaddoverflow() to detect the wrap and compare the resulting endpoint against the buffer size.
In the Linux kernel, the following vulnerability has been resolved:
serial: msm: Disable DMA for kernel console UART
At the moment, concurrent writes from userspace and the kernel to the console can trigger a race condition that results in an infinite loop of the same messages printed over and over again. This is most likely to happen during system startup or shutdown when the init system starts/stops a large number of system services that interact with various kernel code.
When userspace writes to the TTY device, the driver initiates an asynchronous DMA transfer and releases the port lock. At the same moment, the kernel printk path might grab the port lock and re-configure the UART controller for PIO, without waiting for the DMA operation to complete. It seems like this collision results in zero progress being reported for the DMA engine, so the same text is printed to the console over and over again.
For the kernel console, we want a reliable output path that will be functional even during crashes etc. So rather than implementing complex code to synchronize the kernel console write routines with the userspace DMA write routines, simply disable DMA for the console UART instance.
Similar checks exist in many other serial drivers, e.g. 8250port.c, imx.c, sh-sci.c etc.
In the Linux kernel, the following vulnerability has been resolved:
afs: Fix uncancelled rxrpc OOB message handler
Fix AFS to cancel its OOB message processing (typically to respond to security challenges). Also move OOB message processing to afswq so that it's also waited for and make the OOB handler just return if the net namespace is no longer live.
In the Linux kernel, the following vulnerability has been resolved:
ntb: Store original DMA address for future release
The DMA API requires that dmafreeattrs receive the exact dmahandle originally returned by the allocation function. Do not modify it.
In the Linux kernel, the following vulnerability has been resolved:
drm/tegra: gr2d/gr3d: Initialize address register map before HOST1X client is registered
The host1xclientregister() function is called just prior to register map initialization loop, making the device available to userspace. This may result in userspace attempting to submits a job before the register map is initialized. Address this by moving register initialization before host1x client registration.
In the Linux kernel, the following vulnerability has been resolved:
IB/mlx5: Properly support implicit ODP reregmr
Due to all the child mkeys in the implicit ODP configuration we cannot change anything in place for the parent mkey. Instead the whole thing needs to be rebuilt if any change is requested. If the user does not specify a translation then force the implicit values which will then fall through the logic into mlx5ibregusermr() to allocate a completely new MR.
Since implicit children were also touching the mr->pd, this removes another case where the access was racy.
In the Linux kernel, the following vulnerability has been resolved:
ocfs2: fix circular locking dependency in ocfs2dioendiowrite
A circular locking dependency involves INODEALLOCSYSTEMINODE, EXTENTALLOCSYSTEMINODE, and ORPHANDIRSYSTEMINODE.
1. ocfs2mknod() acquires INODEALLOC then EXTENTALLOC.
2. ocfs2dioendiowrite() acquires EXTENTALLOC for unwritten extents, then ORPHANDIR via ocfs2delinodefromorphan() while still holding EXTENTALLOC.
3. ocfs2wipeinode() acquires ORPHANDIR then INODEALLOC via ocfs2removeinode.
Break the cycle in ocfs2dioendiowrite() by freeing the allocation contexts (releasing EXTENTALLOC) before acquiring ORPHANDIR.
WARNING: possible circular locking dependency detected ------------------------------------------------------ is trying to acquire lock: ffff8881e78b33a0 (&ocfs2sysfilelockkey[INODEALLOCSYSTEMINODE]){+.+.}-{4:4}, at: ocfs2evictinode+0x1539/0x43b0 fs/ocfs2/inode.c:1299
but task is already holding lock: ffff8881e78b4fa0 (&ocfs2sysfilelockkey[ORPHANDIRSYSTEMINODE]){+.+.}-{4:4}, at: ocfs2evictinode+0xe97/0x43b0 fs/ocfs2/inode.c:1299
the existing dependency chain (in reverse order) is:
-> #2 (&ocfs2sysfilelockkey[ORPHANDIRSYSTEMINODE]){+.+.}-{4:4}: inodelock include/linux/fs.h:1029 [inline] ocfs2delinodefromorphan+0x12e/0x7a0 fs/ocfs2/namei.c:2728 ocfs2dioendio+0xf9c/0x1370 fs/ocfs2/aops.c:2418 diocomplete+0x25b/0x790 fs/direct-io.c:281
-> #1 (&ocfs2sysfilelockkey[EXTENTALLOCSYSTEMINODE]){+.+.}-{4:4}: inodelock include/linux/fs.h:1029 [inline] ocfs2reservesuballocbits+0x16d/0x4840 fs/ocfs2/suballoc.c:882 ocfs2reservenewmetadatablocks+0x415/0x9a0 fs/ocfs2/suballoc.c:1078 ocfs2mknod+0x10f3/0x2260 fs/ocfs2/namei.c:351
-> #0 (&ocfs2sysfilelockkey[INODEALLOCSYSTEMINODE]){+.+.}-{4:4}: lockacquire+0x15a5/0x2cf0 kernel/locking/lockdep.c:5237 lockacquire+0x106/0x350 kernel/locking/lockdep.c:5868 downwrite+0x96/0x200 kernel/locking/rwsem.c:1625 inodelock include/linux/fs.h:1029 [inline] ocfs2removeinode fs/ocfs2/inode.c:733 [inline] ocfs2wipeinode fs/ocfs2/inode.c:896 [inline] ocfs2deleteinode fs/ocfs2/inode.c:1157 [inline] ocfs2evictinode+0x1539/0x43b0 fs/ocfs2/inode.c:1299
Chain exists of: &ocfs2sysfilelockkey[INODEALLOCSYSTEMINODE] --> &ocfs2sysfilelockkey[EXTENTALLOCSYSTEMINODE] --> &ocfs2sysfilelockkey[ORPHANDIRSYSTEMINODE]
Possible unsafe locking scenario:
CPU0 CPU1 ---- ---- lock(&ocfs2sysfilelockkey[ORPHANDIRSYSTEMINODE]); lock(&ocfs2sysfilelockkey[EXTENTALLOCSYSTEMINODE]); lock(&ocfs2sysfilelockkey[ORPHANDIRSYSTEMINODE]); lock(&ocfs2sysfilelockkey[INODEALLOCSYSTEMINODE]);
DEADLOCK
In the Linux kernel, the following vulnerability has been resolved:
afs: Fix leak of ungot volume
Fix afslookupvolumercu() so that it doesn't leak a dying volume if afstrygetvolume() fails.
In the Linux kernel, the following vulnerability has been resolved:
afs: Fix vllist leak
Fix a leak of the new vllist in afsupdatecell() in the event that it is an empty list (nrservers == 0), in which case the old list isn't displaced unless the old list is also empty.
In the Linux kernel, the following vulnerability has been resolved:
ring-buffer: Fix event length with forced 8-byte alignment
When RBFORCE8BYTEALIGNMENT is true, rbcalculateeventlength() reserves the space of event->array[0] for placing the data length and rbupdateevent() stores the data length in event->array[0] accordingly. As a result the whole event length will add extra 4 bytes for sizeof(event.array[0]) unconditionally.
But ringbuffereventlength() only subtracts the sizeof(event->array[0]) for events larger than RBMAXSMALLDATA + sizeof(event->array[0]). As a result, small events on architectures with RBFORCE8BYTEALIGNMENT=true report a data length that is 4 bytes larger than expected.
To fix it, add the RBFORCE8BYTEALIGNMENT as a condition to subtract the size of that length field whenever RBFORCE8BYTEALIGNMENT is true.
This issue is observed in a riscv64 kernel with CONFIGHAVE64BITALIGNEDACCESS set to y, when we run ftrace selftest tracemarkerraw.tc, we get the weird log: for cases where the id is 1..100, the number of data field is 8N, but once id exceeds 100, the number of data field becomes 8N+4: # 1 buf: 58 00 00 00 80 5e d1 63 (number of data field is 81) ... # a buf: 58 ... (number of data field is 82) ... # 64 buf: 58 ... (number of data field is 813) # 65 buf: 58 ... (number of data field is 813+4)
After applying this change, the number of data field keeps being 8N+4 consistently.
In the Linux kernel, the following vulnerability has been resolved:
ipvs: use parsed transport offset in TCP state lookup
TCP state handling reparses the skb to find the TCP header. For IPv6 it uses sizeof(struct ipv6hdr), while the surrounding IPVS code already parsed the packet with ipvsfilliphskb() and has the real transport-header offset in iph.len.
This makes TCP state handling look at the wrong bytes when an IPv6 packet carries extension headers. Use the parsed transport offset passed down from ipvssetstate() when reading the TCP header.
For IPv4 and for IPv6 packets without extension headers, the passed offset matches the previous value.
In the Linux kernel, the following vulnerability has been resolved:
drm/amdkfd: Validate CRIU-restored IDs before idralloc
The KFD CRIU restore flow restores previously saved object IDs from userspace.
For event restore:
kfdcriurestoreevent() -> createsignalevent() / createotherevent() -> allocateeventnotificationslot() -> idralloc(..., restoreid, restoreid + 1, ...)
For BO restore:
criurestorememoryofgpu() -> idralloc(..., bopriv->idrhandle, ...)
In both cases, the restored ID comes from userspace-provided CRIU data.
idralloc() expects the ID range values to fit within signed int limits. If a restored ID is larger than INTMAX, it can trigger a WARN in the IDR layer.
A kernel WARN is undesirable because it prints a warning trace and may cause a panic or reboot on systems with paniconwarn enabled.
Smatch reported these paths as allowing unchecked userspace values to reach idralloc().
Add INTMAX validation before using restored IDs in:
- kfdcriurestoreevent() - criurestorememoryofgpu()
If the restored ID is invalid, return -EINVAL.
This prevents invalid restore data from reaching the IDR layer and avoids WARN-triggering paths, while keeping valid restore behavior unchanged.
In the Linux kernel, the following vulnerability has been resolved:
ntfs3: Allocate iomap inlinedata using allocpage
This fixes a BUG reported in iomapwriteendinline: iomapinlinedatavalid checks that the inlinedata fits within a page. If the inlinedata is allocated with kmemdup there's no guarantee that it's page-aligned, so the check sometimes fails. Allocate it with allocpage to ensure it's page-aligned.
In the Linux kernel, the following vulnerability has been resolved:
RDMA/rxe: Fix responder UAF on IBQPMAXDESTRDATOMIC modifyqp
rxeqpfromattr() handles IBQPMAXDESTRDATOMIC outside the IBQPSTATE path, so it holds no statelock and runs while the responder task rxereceiver() (recvtask on rxewq) is live. A modifyqp() setting only that attribute calls freerdatomicresources() then allocrdatomicresources(), swapping qp->resp.resources[] while rxeprepareres()/findresource() walk it; freerdatomicresources() also leaves the cached pointer qp->resp.res dangling. A local unprivileged user can race the free/realloc into a use-after-free in rxereceiver() (local DoS).
Drain recvtask around the swap with rxedisabletask()/rxeenabletask(), as rxeqpreset() already does when tearing this array down, re-enabling only after allocrdatomicresources() succeeds so the responder never resumes against a NULL qp->resp.resources on the ENOMEM path. Also clear qp->resp.res in freerdatomicresources(), like the rxeresp.c completion paths.
Reproduced under KASAN; the slab-use-after-free in rxereceiver() is gone.
In the Linux kernel, the following vulnerability has been resolved:
fuse: fix race between interrupt and resend
After commit f8fce75fedf7 ("fuse: clear intrentry in fuseresend and fuseremovependingreq") the WARNON(!listempty(&req->intrentry)) in fuserequestfree() still triggers due to the following race:
In requestwaitanswer() if (testbit(FRSENT, &req->flags)) -> returns true
In fusechanresend() clearbit(FRSENT, &req->flags)
In requestwaitanswer() queueinterrupt(req)
Fix by:
- move clearing FRSENT inside fpq->lock
- move setting FRPENDING inside fiq->lock
- recheck FRSENT after acquiring fiq->lock in fusedevqueueinterrupt()
In the Linux kernel, the following vulnerability has been resolved:
fuse: publish io-uring queues with release semantics
fuseuringcreatequeue() initializes a fuseringqueue and then publishes the pointer into ring->queues[qid] with WRITEONCE() under the fch->lock. There are several readers that may concurrently be fetching that pointer locklessly and then deferencing it.
WRITEONCE() doesn't ensure ordering of the queue's field initialization before the ring->queues[qid] pointer assignment. The queue must be published with smpstorerelease() so the field initialization is guaranteed to happen before.
Readers in paths where the read may happen concurrently with the store need to use READONCE() because any race involving a plain access is undefined.
In the Linux kernel, the following vulnerability has been resolved:
KVM: SEV: Allocate full pages for {DE,EN}CRYPT ops on SNP-enabled hosts
When {de,en}crypting memory of an SEV or SEV-ES guest on an SNP-enabled host via a temporary buffer, allocate a full 4KiB page for the buffer to ensure the page containing the buffer is wholly owned by KVM, i.e. won't be concurrently allocated and accessed by other kernel code while KVM is using the buffer to {de,en}crypt memory. On SNP-enabled platforms, when sending SEV/SEV-ES commands that trigger firmware writes to memory, the to-be-written page(s) must be (temporarily) assigned to Firmware (as required by the SNP architecture, to guard against using such commands as gadgets to attack SNP guests). See snpmapcmdbufdesc() and friends.
Unfortunately, transferring ownership of a page to Firmware makes the page inaccessible to software, and thus writes generate RMP #PF violations. If KVM uses a sub-page allocation for its temporary buffer, some other actor in the kernel can allocate and use the other portions of the page, and thus trigger unexpected (and seemingly spurious) RMP #PF violations due to software attempting to access a Firmware-owned page.
BUG: unable to handle page fault for address: ffff906ae30f0300 #PF: supervisor write access in kernel mode #PF: errorcode(0x80000003) - RMP violation PGD 6b1b80d067 P4D 6b1b80d067 PUD 100231e2063 PMD 10055a88063 PTE 80000100630f0163 SEV-SNP: PFN 0x100630f0 unassigned, dumping non-zero entries in 2M PFN region: [0x10063000 - 0x10063200] Oops: Oops: 0003 [#1] SMP CPU: 70 UID: 0 PID: 10658 Comm: svwWaiterThrea Tainted: G U W O 7.1.0-smp--c22293789940-seanjc-next #1 PREEMPTLAZY Tainted: [U]=USER, [W]=WARN, [O]=OOTMODULE Hardware name: Google, Inc. ArcadiaIT80/ArcadiaIT80, BIOS 34.86.0-102 01/25/2026 RIP: 0010:memset+0xf/0x20 Call Trace: <TASK> kvmallocnodenoprof+0x2a4/0x710 dogetxattr+0x4e/0x130 pathgetxattrat+0x125/0x1b0 dosyscall64+0x10a/0x480 entrySYSCALL64afterhwframe+0x4b/0x53 RIP: 0033:0x7f3a22cb6daa </TASK> Modules linked in: kvmamd kvm irqbypass vfat fat ccp k10temp sha3 libsha3 i2cpiix4 gq(O) cdcacm xhcipci xhcihcd gsmi: Log Shutdown Reason 0x03 CR2: ffff906ae30f0300 ---[ end trace 0000000000000000 ]--- RIP: 0010:memset+0xf/0x20 Kernel panic - not syncing: Fatal exception Kernel Offset: 0x39e00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) gsmi: Log Shutdown Reason 0x02
In the Linux kernel, the following vulnerability has been resolved:
gtp: serialize PDP context updates
PDP contexts can be deleted through GTPCMDDELPDP or while the GTP network device is being unregistered. The latter is serialized by RTNL, but the generic-netlink delete path only holds RCU.
Running both paths concurrently can therefore make both paths delete the same PDP context. The issue was found through static analysis and reproduced on a KASAN-enabled kernel by a simple two-thread program racing GTPCMDDELPDP against RTMDELLINK:
Oops: general protection fault, probably for non-canonical address KASAN: maybe wild-memory-access in range [0xdead000000000120-0xdead000000000127] RIP: gtpgenldelpdp+0x1c1/0x420 [gtp] RBP: dead000000000122
The second deletion dereferenced the poisoned hlist pprev pointer.
Serialize gtppdpadd(), gtpgenldelpdp(), and gtpdellink() with a shared mutex. Keep the mutex held until the final use of a PDP context in the NEWPDP path, and keep the RCU read-side section around the complete PDP context use in the DELPDP path.
In the Linux kernel, the following vulnerability has been resolved:
tcp: fix AO info use-after-free in tcpaoconnectinit()
tcpv4connect() adds a SYN-SENT socket to the ehash before calling tcpconnect(). If TCP-AO is configured, tcpconnect() first verifies that a key matches the peer and the bound device's current L3 master. tcpaoconnectinit() later resolves the L3 master again and removes keys which do not match it.
The socket lock does not stabilize the bound device's VRF membership. Detaching the device from its VRF between the initial validation and the L3-master calculation in tcpaoconnectinit() can therefore make the validation succeed while initialization observes the default L3 domain and removes the only key. The subsequent AO lookup then fails, so the no-key path clears tp->aoinfo and frees it directly.
The receive path can find the socket in the ehash and load tp->aoinfo under RCU before acquiring the socket lock. A reader which loaded the old pointer can thus continue into tcpinboundaohash() after the direct free.
The issue was found during a static audit of TCP-AO object lifetime. An unprivileged reproducer in self-created user and network namespaces raced connect() with detaching a veth from its VRF while sending TCP-AO segments. It triggered the same KASAN report on two fresh boots:
BUG: KASAN: slab-use-after-free in tcpinboundaohash+0x585/0x19f0 Write of size 8 at addr ffff88800bf88128 by task tcpaovrfrace/232
Call Trace: tcpinboundaohash+0x585/0x19f0 tcpinboundhash+0x677/0xa80 tcpv4rcv+0x1c3e/0x3ab0
Allocated by task 235: tcpaoallocinfo+0x43/0xf0 tcpaoaddcmd+0xdf7/0x13b0 dotcpsetsockopt+0x168c/0x2640
Freed by task 235: kfree+0x1b8/0x550 tcpconnect+0x252/0x4f00 tcpv4connect+0x1114/0x1720
The bad address is 40 bytes inside the freed 128-byte object, matching the tcpaoinfo counters.keynotfound field. The two runs used 1000 attempts each, reached the no-key path 366 and 411 times, and produced one and two KASAN reports respectively. With this change, the same reproducer reached the no-key path 366 times in 1000 attempts without a KASAN report or oops.
Use tcpaodestroysock() for the no-key path. It unpublishes the AO info, updates the socket memory and static-key accounting, and defers the free until after an RCU grace period.
Also drop the WARNONONCE() and its stale comment. The VRF detach race makes the no-key state reachable during normal operation, so it is a handled condition rather than an impossible assertion. On paniconwarn kernels the WARN would turn this handled race into a kernel panic.
In the Linux kernel, the following vulnerability has been resolved:
xfrm: espintcp: fix UAF during close
ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcpclose() frees emsg->skb via kfreeskb() without holding any socket lock. Concurrently, the xfrmtransreinject work queue invokes espoutputtcpfinish() -> espintcppushskb() -> espintcppushmsgs() -> skbsendsocklocked(), which reads the same skb as a data source.
Fix this by adding a synchronizercu() call after resetting skprot, since espoutputtcpfinish() runs under RCU and won't use a socket with skprot == &tcpprot. Simply taking the socket lock in espintcpclose() could lead to leaks, if espoutputtcpfinish() re-adds an skb in the slot we just freed. After this, the existing barrier() is no longer needed.
In the Linux kernel, the following vulnerability has been resolved:
tcp: clamp route advmss to TCPMINMSS
tcpselectinitialwindow() assumes that callers never pass an MSS smaller than 1, but route-derived advmss values can violate that assumption.
A too-small explicit RTAXADVMSS is one way to get there, but it is not the only one. The same divide-by-zero can also be reached through the "default advmss" path when RTAXADVMSS is left at 0 and the effective advmss is later driven down by route MTU and minadvmss.
Introduce a tcpdstadvmss() helper that clamps route advmss to TCPMINMSS before TCP consumes it, and use it in the TCP paths that derive advmss from dst metrics. This keeps the effective MSS from dropping to zero before tcpselectinitialwindow() rounds the receive window.