See how linux compares to other vendors in security performance
In the Linux kernel, the following vulnerability has been resolved:
iommu/arm-smmu-v3-iommufd: Require exactly one Stream ID for a vDEVICE
armvsmmuvsidtosid() maps a guest's vSID to a single physical Stream ID taken from master->streams[0], assuming a device has exactly one stream. A device with several streams gets only its first one mapped, so a guest vSID invalidation cannot reach the others' ATC and IOTLB entries; a device with none makes master->streams a ZEROSIZEPTR, read out of bounds.
Add an armvsmmuvdeviceinit() op to reject the vDEVICE with -EOPNOTSUPP when master->numstreams is not one, rather than mapping it silently.
In the Linux kernel, the following vulnerability has been resolved:
ntfs: harden runlist realloc size calculations
Add a shared helper to safely convert runlist element counts to byte sizes using overflow checks, and use it in both ntfsrlrealloc() and ntfsrlreallocnofail().
In the Linux kernel, the following vulnerability has been resolved:
scsi: libiscsitcp: Bound SCSI Response data segment to the connection buffer
iscsitcphdrdissect() receives the data segment of several PDU types into the fixed-size conn->data buffer, which is allocated for ISCSIDEFMAXRECVSEGLEN (8192) bytes. For the LOGINRSP, TEXTRSP, REJECT and ASYNCEVENT opcodes the dissect path already rejects a PDU whose DataSegmentLength exceeds that buffer.
The SCSI Command Response (ISCSIOPSCSICMDRSP) path also copies its data segment (sense/response data) into conn->data via iscsitcpdatarecvprep(), but it does so without the same check. The only upstream bound on in.datalen is conn->maxrecvdlength, the initiator's advertised MaxRecvDataSegmentLength, which is commonly negotiated well above 8192 (open-iscsi defaults to 262144). A target that returns a SCSI Response with a DataSegmentLength between 8193 and maxrecvdlength therefore overflows the 8192-byte conn->data buffer.
Once the same bound applies, ISCSIOPSCSICMDRSP is handled exactly like those responses: bound the data segment, receive it into conn->data when present, and otherwise complete the PDU with no data. Fold the opcode into that case group rather than duplicating the check.
In the Linux kernel, the following vulnerability has been resolved:
rtase: fix double free of multi-frag skb on DMA map failure
In rtasestartxmit(), when the head buffer DMA mapping fails after rtasexmitfrags() has mapped all fragments, the error path clears the fragment descriptors with rtasetxclearrange(), which frees the skb through the last-frag slot and accounts txdropped. Control then falls through to the common error label, which frees the same skb a second time and counts it again.
Return right after clearing the fragments when the skb owns frags; the no-frag case still drops through and frees the head skb once.
In the Linux kernel, the following vulnerability has been resolved:
ksmbd: use memcmp() to compare ClientGUIDs
ClientGUID is a fixed-size binary value and can contain embedded NUL bytes. strncmp() stops comparing at the first NUL byte, so different ClientGUID values can incorrectly be treated as equal.
Use memcmp() in SMB3 multichannel session binding and FSCTLVALIDATENEGOTIATEINFO to compare all SMB2CLIENTGUIDSIZE bytes.
In the Linux kernel, the following vulnerability has been resolved:
KVM: x86: Cancel delayed I/O APIC EOI handling before destroying vCPUs
Cancel (and flush) the I/O APIC's delayed EOI handling work during the "pre VM destroy" phase, before vCPUs are destroyed, as processing the EOI broadcast will inject another IRQ if the line is asserted, i.e. will try to deliver an IRQ to the target vCPU(s). Canceling the work after vCPUs are destroyed leads to UAF if the delayed work is processed after vCPUs are destroyed.
BUG: KASAN: slab-use-after-free in kvmirqdeliverytoapicfast+0x9bf/0xa20 arch/x86/kvm/lapic.c:1250 Read of size 8 at addr ffff8880499abea0 by task kworker/1:2/1218
CPU: 1 UID: 0 PID: 1218 Comm: kworker/1:2 Not tainted 7.1.0-rc7 #5 PREEMPT(lazy) Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Workqueue: events kvmioapiceoiinjectwork Call Trace: <TASK> dumpstack lib/dumpstack.c:94 dumpstacklvl+0x100/0x190 lib/dumpstack.c:120 printaddressdescription mm/kasan/report.c:378 printreport+0x139/0x4ad mm/kasan/report.c:482 kasanreport+0xe4/0x1d0 mm/kasan/report.c:595 kvmirqdeliverytoapicfast+0x9bf/0xa20 arch/x86/kvm/lapic.c:1250 kvmirqdeliverytoapic+0xd8/0xbf0 arch/x86/kvm/lapic.c:1345 kvmirqdeliverytoapic arch/x86/kvm/lapic.h:129 ioapicservice+0x308/0x590 arch/x86/kvm/ioapic.c:492 kvmioapiceoiinjectwork+0x13c/0x190 arch/x86/kvm/ioapic.c:532 processonework+0xa59/0x19a0 kernel/workqueue.c:3314 processscheduledworks kernel/workqueue.c:3397 workerthread+0x5eb/0xe50 kernel/workqueue.c:3478 kthread+0x370/0x450 kernel/kthread.c:436 retfromfork+0x72b/0xd30 arch/x86/kernel/process.c:158 retfromforkasm+0x1a/0x30 arch/x86/entry/entry64.S:245 </TASK>
Note, the VM is unreachable once kvmdestroyvm() starts, and scheduling new work via kvmioapicsendeoi() can only be done via KVMRUN, i.e. requires a live vCPU.
Alternatively, KVM could simply destroy the I/O APIC during the "pre" phase of VM destruction, but that gets more than a bit sketchy as KVM expects the I/O APIC to exist if ioapicinkernel() is true, and nested virtualization in particular has a bad habit of touching VM-scope state during vCPU destruction. E.g. attempting to free the PIC during the pre phase would lead to a NULL pointer dereference in kvmcpuhasextint(), and it's not hard to imagine the I/O APIC having a similar flaw.
In the Linux kernel, the following vulnerability has been resolved:
igbvf: Fix leak in TX DMA error cleanup
If an error is encountered while mapping TX buffers, the driver should unmap any buffers already mapped for that skb.
Because count is incremented before each frag mapping, it will always match the correct number of unmappings needed when dmaerror is reached. Decrementing count before the while loop in dmaerror causes an off-by-one error. If any mapping was successful before an unsuccessful mapping, exactly one DMA mapping (the head) would leak.
This bug was introduced by a 2010 fix for an endless loop in dmaerror. All other affected drivers have already been fixed.
In the Linux kernel, the following vulnerability has been resolved:
net: bridge: stop fast-leave after deleting a port group
brmulticastleavegroup() iterates mp->ports with pp = &p->next in its fast-leave path. After brmulticastdelpg() removes p, continuing the loop advances pp through the deleted entry.
If multicast-to-unicast was enabled, the bridge can hold multiple port groups for the same port and group with different source MAC addresses. Once multicast-to-unicast is disabled, brportgroupequal() matches those entries by port only. A fast leave can then delete one entry and continue from its stale next pointer, leaving mp->ports pointing at a deleted port group.
Fast leave only needs to remove one matching port group. Break after brmulticastdelpg() so the loop stops before dereferencing the removed entry.
In the Linux kernel, the following vulnerability has been resolved:
um: vector: fix use-after-free in vectormmsgrx()
When vectormmsgrx() discards a packet whose overlay header fails verifyheader(), it frees the skb and continues the loop:
if (headercheck < 0) { devkfreeskbirq(skb); vp->estats.rxencapserrors++; continue; }
The normal and short-packet paths fall through to the bottom of the loop body, which clears the consumed slot and advances the cursors:
(skbuffvector) = NULL; mmsgvector++; skbuffvector++;
The verifyheader() < 0 path skips that via continue, so the freed skb is left in skbuffvector[] and the cursors do not advance. The next iteration reads the same slot, gets the freed skb, and frees it again, producing a refcount underflow / use-after-free in the RX path.
Discard the slot the same way the other paths do before continuing.
Only transports whose verifyheader() can return negative are affected: GRE and L2TPv3 do so on a cookie/session-id mismatch (raw/tap do not), so any peer on such a transport can trigger it without authentication.
In the Linux kernel, the following vulnerability has been resolved:
vxlan: use pskbnetworkmaypull() for transmit path header pulls
In vxlanxmit(), arpreduce(), and vxlanmdbentryskbget(), pskbmaypull() was being called to verify the availability of network layer headers (ARP, IPv6/ND, IP/IPv6 MDB keys).
However, during transmit skb->data points to the MAC header, so skbnetworkoffset(skb) is ETHHLEN (14 bytes). Using pskbmaypull(skb, len) only checks len bytes from skb->data rather than skbnetworkoffset(skb) + len, which can leave part of the network header in non-linear frags.
Replace these remaining pskbmaypull() calls with pskbnetworkmaypull() to properly account for the MAC header offset.
In the Linux kernel, the following vulnerability has been resolved:
vxlan: use neighhasnapshot() in routeshortcircuit()
The neighbour hardware address n->ha can be updated asynchronously by the neighbour subsystem, protected by n->halock seqlock. Reading n->ha without holding the seqlock loop can lead to torn reads or reading a partially updated MAC address.
Use neighhasnapshot() in routeshortcircuit() to safely copy n->ha under readseqbegin()/readseqretry() lock protection before using it.
Note that arpreduce() and neighreduce() seem to have the same issue left for future patches.
In the Linux kernel, the following vulnerability has been resolved:
vxlan: use pskbnetworkmaypull() in routeshortcircuit()
routeshortcircuit() currently calls pskbmaypull(skb, sizeof(struct iphdr)) (or ipv6hdr), which checks if bytes are available starting from skb->data.
However, in vxlanxmit(), skb->data points to the MAC header, so skbnetworkoffset(skb) is ETHHLEN (14 bytes). Using pskbmaypull(skb, 20) only checks 20 bytes from skb->data (which is 14 bytes MAC header + 6 bytes of IP header), leaving the rest of the IP header potentially un-pulled in non-linear frags. Subsequent dereferences of iphdr(skb)->daddr can read beyond the pulled linear buffer length.
Fix this by using pskbnetworkmaypull(), which adds skbnetworkoffset(skb) to the length check to ensure the full network header is present in the linear buffer.
In the Linux kernel, the following vulnerability has been resolved:
iommu/vt-d: Clear Present bit before tearing down scalable-mode context entry
devicepasidtableteardown() zeroes the 128-bit scalable-mode context entry with contextclearentry() while the Present bit is still set. This creates a window where the hardware can fetch a torn entry, with some fields already zeroed while Present is still set, leading to unpredictable behavior or spurious faults. The context-cache invalidation is issued only after the entry has been zeroed, and intelpasidfreetable() then frees the PASID directory pages, so the IOMMU can keep walking a stale Present=1 entry that points at freed memory.
While x86 provides strong write ordering, the compiler may reorder the two 64-bit writes to the entry, and the hardware fetch is not guaranteed to be atomic with respect to multiple CPU writes.
Commit c1e4f1dccbe9d ("iommu/vt-d: Clear Present bit before tearing down context entry") fixed this exact pattern in domaincontextclearone() and the copied-context path, but devicepasidtableteardown() was not converted.
Align it with the "Guidance to Software for Invalidations" in the VT-d spec, Section 6.5.3.3, using the same ownership handshake as the sibling fix: clear only the Present bit, flush it to the IOMMU, perform the context-cache invalidation, and only then zero the rest of the entry.
In the Linux kernel, the following vulnerability has been resolved:
rxrpc: serialize kernel accept preallocation with socket teardown
rxrpckernelchargeaccept() reads rx->backlog without any socket/backlog synchronization and passes that raw pointer into rxrpcservicepreallocone(). A concurrent rxrpcdiscardprealloc() sets rx->backlog = NULL and frees the backlog rings, so a kernel preallocation worker can keep using a freed struct rxrpcbacklog while updating backloghead/tail and array slots.
Serialize the state check and backlog lookup with the socket lock, and reject kernel preallocation once teardown has disabled listening or discarded the service backlog.
In the Linux kernel, the following vulnerability has been resolved:
rxrpc: Don't move a peeked OOB message onto the pending queue
rxrpcrecvmsgoob() takes a received oob message off recvmsgoobq and, if a response is needed, moves it onto the pendingoobq tree. However, only the unlink from recvmsgoobq is guarded by MSGPEEK; the move onto pendingoobq always runs.
As a result, reading a challenge with MSGPEEK leaves the skb on recvmsgoobq while also adding it to pendingoobq. Since struct skbuff's rbnode shares storage with its next and prev pointers, rbinsertcolor() overwrites the list linkage, and the skb, which holds a single reference, becomes reachable from both queues at once.
When the socket is closed both queues are drained in turn. While draining recvmsgoobq, skbunlink() follows the next and prev pointers that rbnode has overwritten and writes to a bad address. Also, as the skb holds a single reference but is freed from each queue, both the skb and the connection reference it holds are released twice. This leads to memory corruption and to a use-after-free caused by the connection refcount underflow.
MSGPEEK does not consume the message from the queue, so only unlink it from recvmsgoobq and then move it onto pendingoobq or free it when the message is actually consumed.
In the Linux kernel, the following vulnerability has been resolved:
vxlan: Fix potential null-ptr-deref in vxlangropreparereceive().
udptunnelsockrelease() could set sk->skuserdata to NULL while vxlangropreparereceive() is running.
Let's check if rcudereferenceskuserdata() is NULL after skbgroremcsuminit().
In the Linux kernel, the following vulnerability has been resolved:
dlm: fix add msg handle in sendqueue ordered
In a benchmark scenario triggering a lot of requests that triggers a lot of DLM messages on the network it can be that the mh->seq is not ordered according the oldest seq number. This ordering is required by dlmreceiveack as "before(mh->seq, seq)" will stop to check for older sequence numbers that are ordered in the tail of "node->sendqueue".
The side effects of not having it correct ordered regarding "before(mh->seq, seq)" are refcounting issues and use-after free.
I only was able to reproduce this issue in a experimental DLM branch and a user space DLM benchmark that uses iouring. After changing this I don't experienced any refcounting with the sending buffer issues anymore.
In the Linux kernel, the following vulnerability has been resolved:
ipv6: addrconf: bail out of dadfailure when state is no longer POSTDAD
addrconfdadfailure() transitions ifp->state from DAD to POSTDAD via addrconfdadend(), which drops ifp->lock on return. The lock is re-acquired after netinforatelimited(). A concurrent ipv6deladdr() can take the lock in that window, set ifp->state to DEAD and run listdelrcu(&ifp->iflist).
addrconfdadfailure() then overwrites DEAD with ERRDAD at errdad: and schedules a new dadwork. The work calls ipv6deladdr() again, hitting the already-poisoned list entry:
general protection fault: 0000 [#1] SMP NOPTI CPU: 4 PID: 217 Comm: kworker/4:1 Workqueue: ipv6addrconf addrconfdadwork RIP: 0010:ipv6deladdr+0xe9/0x280 RAX: dead000000000122 Call Trace: addrconfdadstop+0x113/0x140 addrconfdadwork+0x28c/0x430 processonework+0x1eb/0x3b0 workerthread+0x4d/0x400 kthread+0x104/0x140 retfromfork+0x35/0x40
Fold the addrconfdadend() logic into addrconfdadfailure() under a single ifp->lock critical section. The STABLEPRIVACY branch temporarily drops ifp->lock around address regeneration, so at lockerrdad: verify the state is still POSTDAD before transitioning to ERRDAD; bail out otherwise to avoid overwriting a state set by another path while the lock was released.
In the Linux kernel, the following vulnerability has been resolved:
nvme-multipath: fix flex array size in struct nvmenshead
struct nvmenshead contains a flexible array member, currentpath[], which is indexed using the NUMA node ID: head->currentpath[numanodeid()]
The structure is currently allocated as: size = sizeof(struct nvmenshead) + (numpossiblenodes() sizeof(struct nvmens )); head = kzalloc(size, GFPKERNEL);
This allocation assumes that NUMA node IDs are sequential and densely packed from 0 .. numpossiblenodes() - 1. While this assumption holds on many systems, it is not always true on some architectures such as powerpc.
On some powerpc systems, NUMA node IDs can be sparse. For example: NUMA: NUMA node(s): 6 NUMA node0 CPU(s): 80-159 NUMA node8 CPU(s): 0-79 NUMA node252 CPU(s): NUMA node253 CPU(s): NUMA node254 CPU(s): NUMA node255 CPU(s):
That is, the possible/online NUMA node IDs are: 0, 8, 252, 253, 254, 255 In this case: numpossiblenodes() = 6
So memory is allocated for only 6 entries in currentpath[]. However, the array is later indexed using the actual NUMA node ID. As a result, accesses such as: head->currentpath[8] or head->currentpath[252] goes out of bounds, leading to the following KASAN splat:
================================================================== BUG: KASAN: slab-out-of-bounds in nvmempathrevalidatepaths+0x22c/0x290 [nvmecore] Write of size 8 at addr c00020003bda35b8 by task kworker/u641:2/1997
CPU: 1 UID: 0 PID: 1997 Comm: kworker/u641:2 Not tainted 7.1.0-rc5-dirty #14 PREEMPT(lazy) Hardware name: 8335-GTH POWER9 0x4e1202 opal:skiboot-v6.5.3-35-g1851b2a06 PowerNV Workqueue: async asyncrunentryfn Call Trace: [c000200037fa7510] [c0000000021c23d4] dumpstacklvl+0x88/0xdc (unreliable) [c000200037fa7540] [c0000000009fda90] printreport+0x22c/0x67c [c000200037fa7630] [c0000000009fd508] kasanreport+0x108/0x220 [c000200037fa7740] [c0000000009fff48] asanstore8+0xe8/0x120 [c000200037fa7760] [c008000018e76474] nvmempathrevalidatepaths+0x22c/0x290 [nvmecore] [c000200037fa7800] [c008000018e6556c] nvmeupdatensinfo+0x4a4/0x5e0 [nvmecore] [c000200037fa7a50] [c008000018e66270] nvmeallocns+0x6d8/0x1a70 [nvmecore] [c000200037fa7c20] [c008000018e679fc] nvmescanns+0x3f4/0x630 [nvmecore] [c000200037fa7d10] [c00000000031f22c] asyncrunentryfn+0x9c/0x3a0 [c000200037fa7db0] [c0000000002fa544] processonework+0x414/0xa10 [c000200037fa7ec0] [c0000000002fbf00] workerthread+0x320/0x640 [c000200037fa7f80] [c00000000030d0f8] kthread+0x278/0x290 [c000200037fa7fe0] [c00000000000ded8] startkernelthread+0x14/0x18
Allocated by task 1997 on cpu 1 at 35.928317s:
The buggy address belongs to the object at c00020003bda3000 which belongs to the cache kmalloc-rnd-15-2k of size 2048 The buggy address is located 16 bytes to the right of allocated 1448-byte region [c00020003bda3000, c00020003bda35a8)
The buggy address belongs to the physical page:
Memory state around the buggy address: c00020003bda3480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c00020003bda3500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c00020003bda3580: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc ^ c00020003bda3600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc c00020003bda3680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ==================================================================
Fix this by allocating the flexible array using nrnodeids instead of numpossiblenodes(). Since nrnodeids represents the maximum possible NUMA node IDs, indexing currentpath[] using numanodeid() becomes safe even on systems with sparse node IDs.
In the Linux kernel, the following vulnerability has been resolved:
nvme: fix FDP fdpcidx bounds check
The fdpcidx bounds check sets n = NUMFDPC + 1 but used > instead of >=, incorrectly accepting fdpidx when it equals n (i.e. NUMFDPC + 1).
In the Linux kernel, the following vulnerability has been resolved:
RDMA/siw: Fix endpoint/socket association handling
Disassociating a socket from an endpoint via siwsocketdisassoc() may release the last reference on that endpoint and free it. Therefore, don't clear the endpoints socket pointer after calling that function, but within.
This fixes a:
BUG: KASAN: slab-use-after-free in siwcmworkhandler (drivers/infiniband/sw/siw/siwcm.c:1053 drivers/infiniband/sw/siw/siwcm.c:1075)
which occurred after processing a malformed MPA request during connection establishment, causing the new endpoint to be closed.
In the Linux kernel, the following vulnerability has been resolved:
lockd: Avoid hashing uninitialized bytes in nlm4svclookupfile()
filehash() digests the first LOCKDFHHASHSIZE bytes of nfsfh.data when bucketing nlmfiles[], independent of fh.size. Commit 3de744ee4e45 ("lockd: Use xdrgen XDR functions for the NLMv4 TEST procedure") set .pcargzero to zero for the converted procedures and moved file-handle population into nlm4svclookupfile(), which copies only xdrlock->fh.len bytes into lock->fh.data.
When an NLMv4 client presents a file handle shorter than LOCKDFHHASHSIZE, bytes fh.len..31 retain whatever the argument buffer held from an earlier request. The same wire handle then hashes to different buckets across calls; nlmlookupfile() misses the existing nlmfile entry, and lock-state lookups fail.
Zero only the tail bytes that filehash() would otherwise consume. Handles of LOCKDFHHASHSIZE or larger already populate every byte that filehash() reads.
In the Linux kernel, the following vulnerability has been resolved:
vhost/net: complete zerocopy ubufs only once
vhost-net initializes one ubufinfo per outstanding zerocopy TX descriptor and hands it to the backend socket. The networking stack may then clone a zerocopy skb before all skb references are released. For example, batman-adv fragmentation reaches skbsplit(), which calls skbzerocopyclone() and increments the same ubufinfo refcount.
vhostzerocopycomplete() currently treats every ubuf callback as a completed vhost descriptor. It dereferences ubuf->ctx, writes the descriptor completion state, and drops the vhostnetubufref even when the callback only releases a cloned skb reference. A backend reset can therefore wait for and free the vhostnetubufref while another cloned skb still carries the same ubufinfo. A later completion then dereferences the freed ubufs pointer.
KASAN reports the stale completion as:
BUG: KASAN: slab-use-after-free in vhostzerocopycomplete+0x1d7/0x1f0 BUG: KASAN: slab-use-after-free in vhostzerocopycomplete+0x101/0x1f0 vhostzerocopycomplete skbcopyubufs devforwardskb2 vethxmit
The freed object was allocated from vhostnetioctl() while setting the backend and freed through kfreercu()/kvfreercubulk after backend removal, while delayed skb completion still reached vhostzerocopycomplete().
Honor the generic ubufinfo refcount before touching vhost state, and run the vhost descriptor completion only for the final ubuf reference. This matches the msgzerocopycomplete() ownership rule for cloned zerocopy skbs.
In the Linux kernel, the following vulnerability has been resolved:
vdpa/octeonep: fix IRQ-to-ring mapping in interrupt handler
Look up the IRQ index in octhw->irqs instead of assuming irq - irqs[0]. This supports non-contiguous IRQ numbers and avoids incorrect ring indexing when irqs[0] is not the base.
In the Linux kernel, the following vulnerability has been resolved:
sctp: validate embedded address parameter length
sctpverifyasconf() and sctpverifyparam() only validate ADDIP, DELIP, and SETPRIMARY parameters against a fixed minimum size of sizeof(struct sctpaddipparam) + sizeof(struct sctpparamhdr). This ensures the outer parameter is large enough to contain an embedded address parameter header, but does not verify that the embedded address parameter's declared length fits within the bounds of the outer parameter.
Later, sctpprocessparam() and sctpprocessasconfparam() extract the embedded address parameter and pass it to af->fromaddrparam(), which uses the address parameter length to parse the variable-length address payload. A malformed peer can therefore advertise an embedded address parameter length that exceeds the remaining bytes in the enclosing parameter.
Validate that addrparam->p.length does not exceed the space available after the sctpaddipparam header before processing the embedded address parameter. Reject malformed parameters when the embedded address length extends beyond the enclosing parameter bounds.
This prevents out-of-bounds reads when parsing malformed parameters carried in INIT or ASCONF processing paths.
In the Linux kernel, the following vulnerability has been resolved:
crypto: cavium/cpt - fix DMA cleanup using wrong loop index
The sgcleanup error path used list[i] instead of list[j] when unmapping DMA buffers, leaking successfully mapped entries and repeatedly unmapping the failed one.
In the Linux kernel, the following vulnerability has been resolved:
bnxt: fix head underflow on XDP head-grow
The xdp.py test testxdpnativeadjstheadgrowdata crashes when run on a bnxt machine (and also crashes in NIPA).
It seems that the bug is an underflow in bnxtrxmultipageskb, which builds the skb head:
napibuildskb(dataptr - bp->rxoffset, rxr->rxpagesize);
The problem with this expression is that in page mode, rxoffset is:
bp->rxoffset = NETIPALIGN + XDPPACKETHEADROOM;
Which evaluates (at least on x8664) to 258.
The test testxdpnativeadjstheadgrowdata tests a case where the head is adjusted by -256.
When this test runs, dataptr is shifted to fragstart + 2 (where fragstart = pageaddress(page) + offset).
Then, bnxtrxmultipageskb is invoked and the napibuildskb expression subtracts 258, landing at an address before fragstart. This could be either the previous fragment or the previous physical page when the offset is < 256 (e.g. if the fragment started at offset 0).
When the skb is freed, the page pool fragment reference is dropped on either the wrong page or the wrong frag of the right page. In either case, the corrupted reference count can lead to the page being prematurely recycled while still in use. Once (incorrectly) recycled, it can be handed out again and on driver teardown this would result in a double free.
The commit under fixes updated this code to handle the case where the native page size is >= 64k, but it unintentionally broke the head grow case.
To fix this, add an offset field to struct bnxtswrxbd, mirroring the existing offset field in struct bnxtswrxaggbd. Populate it on allocation and preserve it on reuse.
In bnxtrxmultipageskb, use the newly added offset field to compute the fragment start and pass that to napibuildskb. Adjust the layout with skbreserve.
There are two cases, the non-adjustment case and the adjustment case.
In both cases, the skb is built at pageaddress(page) + offset to account for the case where the native page size >= 64K and skbreserve is called with dataptr - (pageaddress(page) + offset). That difference equals bp->rxoffset when dataptr was not moved, or bp->rxoffset + xdpadjust when XDP adjusted the head.
Re-running the failing test with this commit applied causes the test to run successfully to completion.
The other rxskbfunc implementations don't have this issue.
In the Linux kernel, the following vulnerability has been resolved:
tcp: clear sockops cb flags before force-closing a child socket
A child socket inherits the listener's bpfsockopscbflags via skclonelock(). If its setup fails in tcpv4synrecvsock() / tcpv6synrecvsock(), the child is freed through putandexit, where inetcskprepareforcedclose() drops the socket lock and tcpdone() runs without it.
If BPFSOCKOPSSTATECBFLAG was inherited, tcpdone() -> tcpsetstate() calls tcpcallbpf(), which expects the lock and trips sockownedbyme():
WARNING: include/net/sock.h:1799 at tcpsetstate+0x433/0x550 RIP: 0010:tcpsetstate+0x433/0x550 include/net/sock.h:1799 Call Trace: <IRQ> tcpdone+0xba/0x250 net/ipv4/tcp.c:5095 tcpv4synrecvsock+0x850/0xa50 net/ipv4/tcpipv4.c:1787 tcpcheckreq+0xf30/0x1360 net/ipv4/tcpminisocks.c:926 tcpv4rcv+0x1047/0x1b50 net/ipv4/tcpipv4.c:2164 </IRQ>
The child is freed before it is ever established, so it should run no sockops callback. Clear its cb flags in inetcskpreparefordestroysock(), the common point for the IPv4, IPv6 and chtls forced-close paths and for the MPTCP ->synrecvsock() failure path (disposechild), which reaches tcpdone() on a child that was never established too.
In the Linux kernel, the following vulnerability has been resolved:
net/sched: schcodel: Do not call qdisctreereducebacklog during peek before restoring qlen
Whenever codel drops packets during peek, it calls qdisctreereducebacklog. An issue arises because it calls qdisctreereducebacklog before it reincrements the qlen. If qlen drops to zero, but peek returns an skb, the parent's qlennotify callback will be executed even though codel still has 1 packet on the queue and, thus, will mistakenly deactivate the parent's class causing issues like a wild memory access when qfq has codel as a child:
[ 36.339843][ T370] Oops: general protection fault, probably for non-canonical address 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI [ 36.340408][ T370] KASAN: maybe wild-memory-access in range [0xdead000000000120-0xdead000000000127] [ 36.340737][ T370] CPU: 2 UID: 0 PID: 370 Comm: tc Not tainted 7.1.0-rc5-00287-g66e13b626592 #87 PREEMPT(full) [ 36.341113][ T370] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 36.341357][ T370] RIP: 0010:qfqdeactivateagg (include/linux/list.h:1029 (discriminator 2) include/linux/list.h:1043 (discriminator 2) net/sched/schqfq.c:1369 (discriminator 2) net/sched/schqfq.c:1395 (discriminator 2)) schqfq [ 36.342221][ T370] RSP: 0018:ffff8881100ef370 EFLAGS: 00010216 [ 36.342422][ T370] RAX: 0000000000000000 RBX: ffff8881058a9568 RCX: dffffc0000000000 [ 36.342664][ T370] RDX: 1ffff11021064dc3 RSI: ffff888108326e00 RDI: dffffc0000000000 [ 36.342905][ T370] RBP: ffff8881058a8280 R08: dead000000000122 R09: 1bd5a00000000024 [ 36.343140][ T370] R10: fffffbfff2940329 R11: fffffbfff2940329 R12: 0000000000000000 [ 36.343383][ T370] R13: dead000000000100 R14: ffff8881058a9580 R15: ffff8881058a9578 [ 36.343631][ T370] FS: 00007fc04b0ca780(0000) GS:ffff888184fef000(0000) knlGS:0000000000000000 [ 36.343911][ T370] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.344116][ T370] CR2: 0000557c02c02000 CR3: 000000010e0ba000 CR4: 0000000000750ef0 [ 36.344359][ T370] PKRU: 55555554 [ 36.344481][ T370] Call Trace: ... [ 36.345054][ T370] qfqresetqdisc (net/sched/schqfq.c:357 net/sched/schqfq.c:1487) schqfq [ 36.345222][ T370] qdiscreset (net/sched/schgeneric.c:1057) [ 36.345503][ T370] qdiscdestroy (net/sched/schgeneric.c:1096) [ 36.345677][ T370] qdiscgraft (net/sched/schapi.c:1062 net/sched/schapi.c:1053 net/sched/schapi.c:1159) [ 36.346335][ T370] tcgetqdisc (net/sched/schapi.c:1528 net/sched/schapi.c:1556)
Fix this by only calling qdisctreereducebacklog in peek after the qlen is restored.
In the Linux kernel, the following vulnerability has been resolved:
tipc: fix UAF in tipcl2sendmsg()
Syzbot reported a slab-use-after-free in ipvlanhardheader() when called from tipcl2sendmsg().
The root cause is that tipcdisablel2media() calls synchronizenet() while b->mediaptr is still valid. This allows concurrent RCU readers to obtain the device pointer after synchronizenet() has finished. The pointer is cleared later in bearerdisable(), but without any subsequent synchronization, allowing the device to be freed while still in use by readers.
Fix this by clearing b->mediaptr in tipcdisablel2media() before calling synchronizenet().
This is safe to do now because the call order in bearerdisable() was reversed in 0d051bf93c06 ("tipc: make bearer packet filtering generic") to call tipcnodedeletelinks() (which needs the pointer) before disablemedia().
https: //lore.kernel.org/netdev/6a2c1007.428ffe26.258b27.015d.GAE@google.com/T/#u