In the Linux kernel, the following vulnerability has been resolved:
skbuff: fix coalescing for pagepool fragment recycling
Fix a use-after-free when using pagepool with page fragments. We encountered this problem during normal RX in the hns3 driver:
(1) Initially we have three descriptors in the RX queue. The first one allocates PAGE1 through pagepool, and the other two allocate one half of PAGE2 each. Page references look like this:
RXBD1 PAGE1 RXBD2 PAGE2 RXBD3 /
(2) Handle RX on the first descriptor. Allocate SKB1, eventually added to the receive queue by tcpqueuercv().
(3) Handle RX on the second descriptor. Allocate SKB2 and pass it to netifreceiveskb():
netifreceiveskb(SKB2) iprcv(SKB2) SKB3 = skbclone(SKB2)
SKB2 and SKB3 share a reference to PAGE2 through skbshinfo()->dataref. The other ref to PAGE2 is still held by RXBD3:
SKB2 ---+- PAGE2 SKB3 / / RXBD3 /
(3b) Now while handling TCP, coalesce SKB3 with SKB1:
tcpv4rcv(SKB3) tcptrycoalesce(to=SKB1, from=SKB3) // succeeds kfreeskbpartial(SKB3) skbreleasedata(SKB3) // drops one dataref
SKB1 PAGE1 \ SKB2 PAGE2 / RXBD3 /
In skbtrycoalesce(), skbfragref() takes a page reference to PAGE2, where it should instead have increased the pagepool frag reference, ppfragcount. Without coalescing, when releasing both SKB2 and SKB3, a single reference to PAGE2 would be dropped. Now when releasing SKB1 and SKB2, two references to PAGE2 will be dropped, resulting in underflow.
(3c) Drop SKB2:
afpacketrcv(SKB2) consumeskb(SKB2) skbreleasedata(SKB2) // drops second dataref pagepoolreturnskbpage(PAGE2) // drops one ppfragcount
SKB1 PAGE1 \ PAGE2 / RXBD3 /
(4) Userspace calls recvmsg() Copies SKB1 and releases it. Since SKB3 was coalesced with SKB1, we release the SKB3 page as well:
tcpeatrecvskb(SKB1) skbreleasedata(SKB1) pagepoolreturnskbpage(PAGE1) pagepoolreturnskbpage(PAGE2) // drops second ppfragcount
(5) PAGE2 is freed, but the third RX descriptor was still using it! In our case this causes IOMMU faults, but it would silently corrupt memory if the IOMMU was disabled.
Change the logic that checks whether pprecycle SKBs can be coalesced. We still reject differing pprecycle between 'from' and 'to' SKBs, but in order to avoid the situation described above, we also reject coalescing when both 'from' and 'to' are pprecycled and 'from' is cloned.
The new logic allows coalescing a cloned pprecycle SKB into a page refcounted one, because in this case the release (4) will drop the right reference, the one taken by skbtrycoalesce().
In the Linux kernel, the following vulnerability has been resolved:
nfsd: clear aclaccess/acldefault after releasing them
If getting acldefault fails, aclaccess and acldefault will be released simultaneously. However, aclaccess will still retain a pointer pointing to the released posixacl, which will trigger a WARNING in nfs3svcreleasegetacl like this:
------------[ cut here ]------------ refcountt: underflow; use-after-free. WARNING: CPU: 26 PID: 3199 at lib/refcount.c:28 refcountwarnsaturate+0xb5/0x170 Modules linked in: CPU: 26 UID: 0 PID: 3199 Comm: nfsd Not tainted 6.12.0-rc6-00079-g04ae226af01f-dirty #8 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 RIP: 0010:refcountwarnsaturate+0xb5/0x170 Code: cc cc 0f b6 1d b3 20 a5 03 80 fb 01 0f 87 65 48 d8 00 83 e3 01 75 e4 48 c7 c7 c0 3b 9b 85 c6 05 97 20 a5 03 01 e8 fb 3e 30 ff <0f> 0b eb cd 0f b6 1d 8a3 RSP: 0018:ffffc90008637cd8 EFLAGS: 00010282 RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffffffff83904fde RDX: dffffc0000000000 RSI: 0000000000000008 RDI: ffff88871ed36380 RBP: ffff888158beeb40 R08: 0000000000000001 R09: fffff520010c6f56 R10: ffffc90008637ab7 R11: 0000000000000001 R12: 0000000000000001 R13: ffff888140e77400 R14: ffff888140e77408 R15: ffffffff858b42c0 FS: 0000000000000000(0000) GS:ffff88871ed00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000562384d32158 CR3: 000000055cc6a000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> ? refcountwarnsaturate+0xb5/0x170 ? warn+0xa5/0x140 ? refcountwarnsaturate+0xb5/0x170 ? reportbug+0x1b1/0x1e0 ? handlebug+0x53/0xa0 ? excinvalidop+0x17/0x40 ? asmexcinvalidop+0x1a/0x20 ? ticknohztickstopped+0x1e/0x40 ? refcountwarnsaturate+0xb5/0x170 ? refcountwarnsaturate+0xb5/0x170 nfs3svcreleasegetacl+0xc9/0xe0 svcprocesscommon+0x5db/0xb60 ? pfxsvcprocesscommon+0x10/0x10 ? rcureadunlock+0x69/0xa0 ? pfxnfsddispatch+0x10/0x10 ? svcxprtreceived+0xa1/0x120 ? xdrinitdecode+0x11d/0x190 svcprocess+0x2a7/0x330 svchandlexprt+0x69d/0x940 svcrecv+0x180/0x2d0 nfsd+0x168/0x200 ? pfxnfsd+0x10/0x10 kthread+0x1a2/0x1e0 ? kthread+0xf4/0x1e0 ? pfxkthread+0x10/0x10 retfromfork+0x34/0x60 ? pfxkthread+0x10/0x10 retfromforkasm+0x1a/0x30 </TASK> Kernel panic - not syncing: kernel: paniconwarn set ...
Clear aclaccess/acldefault after posixaclrelease is called to prevent UAF from being triggered.
In the Linux kernel, the following vulnerability has been resolved:
tls: fix handling of zero-length records on the rxlist
Each recvmsg() call must process either - only contiguous DATA records (any number of them) - one non-DATA record
If the next record has different type than what has already been processed we break out of the main processing loop. If the record has already been decrypted (which may be the case for TLS 1.3 where we don't know type until decryption) we queue the pending record to the rxlist. Next recvmsg() will pick it up from there.
Queuing the skb to rxlist after zero-copy decrypt is not possible, since in that case we decrypted directly to the user space buffer, and we don't have an skb to queue (darg.skb points to the ciphertext skb for access to metadata like length).
Only data records are allowed zero-copy, and we break the processing loop after each non-data record. So we should never zero-copy and then find out that the record type has changed. The corner case we missed is when the initial record comes from rxlist, and it's zero length.
In the Linux kernel, the following vulnerability has been resolved:
NFSD: Protect against send buffer overflow in NFSv2 READ
Since before the git era, NFSD has conserved the number of pages held by each nfsd thread by combining the RPC receive and send buffers into a single array of pages. This works because there are no cases where an operation needs a large RPC Call message and a large RPC Reply at the same time.
Once an RPC Call has been received, svcprocess() updates svcrqst::rqres to describe the part of rqpages that can be used for constructing the Reply. This means that the send buffer (rqres) shrinks when the received RPC record containing the RPC Call is large.
A client can force this shrinkage on TCP by sending a correctly- formed RPC Call header contained in an RPC record that is excessively large. The full maximum payload size cannot be constructed in that case.
In the Linux kernel, the following vulnerability has been resolved:
ice: fix Rx page leak on multi-buffer frames
The iceputrxmbuf() function handles calling iceputrxbuf() for each buffer in the current frame. This function was introduced as part of handling multi-buffer XDP support in the ice driver.
It works by iterating over the buffers from firstdesc up to 1 plus the total number of fragments in the frame, cached from before the XDP program was executed.
If the hardware posts a descriptor with a size of 0, the logic used in iceputrxmbuf() breaks. Such descriptors get skipped and don't get added as fragments in iceaddxdpfrag. Since the buffer isn't counted as a fragment, we do not iterate over it in iceputrxmbuf(), and thus we don't call iceputrxbuf().
Because we don't call iceputrxbuf(), we don't attempt to re-use the page or free it. This leaves a stale page in the ring, as we don't increment nexttoalloc.
The icereuserxpage() assumes that the nexttoalloc has been incremented properly, and that it always points to a buffer with a NULL page. Since this function doesn't check, it will happily recycle a page over the top of the nexttoalloc buffer, losing track of the old page.
Note that this leak only occurs for multi-buffer frames. The iceputrxmbuf() function always handles at least one buffer, so a single-buffer frame will always get handled correctly. It is not clear precisely why the hardware hands us descriptors with a size of 0 sometimes, but it happens somewhat regularly with "jumbo frames" used by 9K MTU.
To fix iceputrxmbuf(), we need to make sure to call iceputrxbuf() on all buffers between firstdesc and nexttoclean. Borrow the logic of a similar function in i40e used for this same purpose. Use the same logic also in icegetpgcnts().
Instead of iterating over just the number of fragments, use a loop which iterates until the current index reaches to the nexttoclean element just past the current frame. Unlike i40e, the iceputrxmbuf() function does call iceputrxbuf() on the last buffer of the frame indicating the end of packet.
For non-linear (multi-buffer) frames, we need to take care when adjusting the pagecntbias. An XDP program might release fragments from the tail of the frame, in which case that fragment page is already released. Only update the pagecntbias for the first descriptor and fragments still remaining post-XDP program. Take care to only access the shared info for fragmented buffers, as this avoids a significant cache miss.
The xdpxmit value only needs to be updated if an XDP program is run, and only once per packet. Drop the xdpxmit pointer argument from iceputrxmbuf(). Instead, set xdpxmit in the icecleanrxirq() function directly. This avoids needing to pass the argument and avoids an extra bit-wise OR for each buffer in the frame.
Move the increment of the ntc local variable to ensure its updated before all calls to icegetpgcnts() or iceputrxmbuf(), as the loop logic requires the index of the element just after the current frame.
Now that we use an index pointer in the ring to identify the packet, we no longer need to track or cache the number of fragments in the rxring.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: nfsetpipapoavx2: fix initial map fill
If the first field doesn't cover the entire start map, then we must zero out the remainder, else we leak those bits into the next match round map.
The early fix was incomplete and did only fix up the generic C implementation.
A followup patch adds a test case to nftconcatrange.sh.
In the Linux kernel, the following vulnerability has been resolved:
scsi: qla2xxx: Implement ref count for SRB
The timeout handler and the done function are racing. When qla2x00asynciocbtimeout() starts to run it can be preempted by the normal response path (via the firmware?). qla24xxasyncgpscspdone() releases the SRB unconditionally. When scheduling back to qla2x00asynciocbtimeout() qla24xxasyncabortcmd() will access an freed sp->qpair pointer:
qla2xxx [0000:83:00.0]-2871:0: Async-gpsc timeout - hdl=63d portid=234500 50:06:0e:80:08:77:b6:21. qla2xxx [0000:83:00.0]-2853:0: Async done-gpsc res 0, WWPN 50:06:0e:80:08:77:b6:21 qla2xxx [0000:83:00.0]-2854:0: Async-gpsc OUT WWPN 20:45:00:27:f8:75:33:00 speeds=2c00 speed=0400. qla2xxx [0000:83:00.0]-28d8:0: qla24xxhandlegpscevent 50:06:0e:80:08:77:b6:21 DS 7 LS 6 rc 0 login 1|1 rscn 1|0 lid 5 BUG: unable to handle kernel NULL pointer dereference at 0000000000000004 IP: qla24xxasyncabortcmd+0x1b/0x1c0 [qla2xxx]
Obvious solution to this is to introduce a reference counter. One reference is taken for the normal code path (the 'good' case) and one for the timeout path. As we always race between the normal good case and the timeout/abort handler we need to serialize it. Also we cannot assume any order between the handlers. Since this is slow path we can use proper synchronization via locks.
When we are able to cancel a timer (deltimer returns 1) we know there can't be any error handling in progress because the timeout handler hasn't expired yet, thus we can safely decrement the refcounter by one.
If we are not able to cancel the timer, we know an abort handler is running. We have to make sure we call sp->done() in the abort handlers before calling krefput().
In the Linux kernel, the following vulnerability has been resolved:
virtio-net: ensure the received length does not exceed allocated size
In xdplinearizepage, when reading the following buffers from the ring, we forget to check the received length with the true allocate size. This can lead to an out-of-bound read. This commit adds that missing check.
In the Linux kernel, the following vulnerability has been resolved:
smb: client: fix in-place encryption corruption in SMB2write()
SMB2write() places write payload in iov[1..n] as part of rqiov. smb3inittransformrq() pointer-shares rqiov, so cryptmessage() encrypts iov[1] in-place, replacing the original plaintext with ciphertext. On a replayable error, the retry sends the same iov[1] which now contains ciphertext instead of the original data, resulting in corruption.
The corruption is most likely to be observed when connections are unstable, as reconnects trigger write retries that re-send the already-encrypted data.
This affects SFU mknod, MF symlinks, etc. On kernels before 6.10 (prior to the netfs conversion), sync writes also used this path and were similarly affected. The async write path wasn't unaffected as it uses rqiter which gets deep-copied.
Fix by moving the write payload into rqiter via ioviterkvec(), so smb3inittransformrq() deep-copies it before encryption.
In the Linux kernel, the following vulnerability has been resolved:
net: bridge: fix vlan tunnel dst refcnt when egressing
The egress tunnel code uses dstclone() and directly sets the result which is wrong because the entry might have 0 refcnt or be already deleted, causing number of problems. It also triggers the WARNON() in dsthold()[1] when a refcnt couldn't be taken. Fix it by using dstholdsafe() and checking if a reference was actually taken before setting the dst.
[1] dmesg WARNON log and following refcnt errors WARNING: CPU: 5 PID: 38 at include/net/dst.h:230 brhandleegressvlantunnel+0x10b/0x134 [bridge] Modules linked in: 8021q garp mrp bridge stp llc bonding ipv6 virtionet CPU: 5 PID: 38 Comm: ksoftirqd/5 Kdump: loaded Tainted: G W 5.13.0-rc3+ #360 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014 RIP: 0010:brhandleegressvlantunnel+0x10b/0x134 [bridge] Code: e8 85 bc 01 e1 45 84 f6 74 90 45 31 f6 85 db 48 c7 c7 a0 02 19 a0 41 0f 94 c6 31 c9 31 d2 44 89 f6 e8 64 bc 01 e1 85 db 75 02 <0f> 0b 31 c9 31 d2 44 89 f6 48 c7 c7 70 02 19 a0 e8 4b bc 01 e1 49 RSP: 0018:ffff8881003d39e8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffffa01902a0 RBP: ffff8881040c6700 R08: 0000000000000000 R09: 0000000000000001 R10: 2ce93d0054fe0d00 R11: 54fe0d00000e0000 R12: ffff888109515000 R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000401 FS: 0000000000000000(0000) GS:ffff88822bf40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f42ba70f030 CR3: 0000000109926000 CR4: 00000000000006e0 Call Trace: brhandlevlan+0xbc/0xca [bridge] brforward+0x23/0x164 [bridge] deliverclone+0x41/0x48 [bridge] brhandleframefinish+0x36f/0x3aa [bridge] ? skbdst+0x2e/0x38 [bridge] ? brhandleingressvlantunnel+0x3e/0x1c8 [bridge] ? brhandleframefinish+0x3aa/0x3aa [bridge] brhandleframe+0x2c3/0x377 [bridge] ? skbpull+0x33/0x51 ? vlandoreceive+0x4f/0x36a ? brhandleframefinish+0x3aa/0x3aa [bridge] netifreceiveskbcore+0x539/0x7c6 ? listdelentryvalid+0x16e/0x1c2 netifreceiveskblistcore+0x6d/0xd6 netifreceiveskblistinternal+0x1d9/0x1fa gronormallist+0x22/0x3e devgroreceive+0x55b/0x600 ? detachbufsplit+0x58/0x140 napigroreceive+0x94/0x12e virtnetpoll+0x15d/0x315 [virtionet] napipoll+0x2c/0x1c9 netrxaction+0xe6/0x1fb dosoftirq+0x115/0x2d8 runksoftirqd+0x18/0x20 smpbootthreadfn+0x183/0x19c ? smpbootunregisterpercputhread+0x66/0x66 kthread+0x10a/0x10f ? kthreadmoddelayedwork+0xb6/0xb6 retfromfork+0x22/0x30 ---[ end trace 49f61b07f775fd2b ]--- dstrelease: dst:00000000c02d677a refcnt:-1 dstrelease underflow
In the Linux kernel, the following vulnerability has been resolved:
RDMA/cma: Ensure rdmaaddrcancel() happens before issuing more requests
The FSM can run in a circle allowing rdmaresolveip() to be called twice on the same idpriv. While this cannot happen without going through the work, it violates the invariant that the same address resolution background request cannot be active twice.
CPU 1 CPU 2
rdmaresolveaddr(): RDMACMIDLE -> RDMACMADDRQUERY rdmaresolveip(addrhandler) #1
processonereq(): for #1 addrhandler(): RDMACMADDRQUERY -> RDMACMADDRBOUND mutexunlock(&idpriv->handlermutex); [.. handler still running ..]
rdmaresolveaddr(): RDMACMADDRBOUND -> RDMACMADDRQUERY rdmaresolveip(addrhandler) !! two requests are now on the reqlist
rdmadestroyid(): destroyidhandlerunlock(): destroyid(): cmacanceloperation(): rdmaaddrcancel()
// processonereq() self removes it spinlockbh(&lock); canceldelayedwork(&req->work); if (!listempty(&req->list)) == true
! rdmaaddrcancel() returns after processonreq #1 is done
kfree(idpriv)
processonereq(): for #2 addrhandler(): mutexlock(&idpriv->handlermutex); !! Use after free on idpriv
rdmaaddrcancel() expects there to be one req on the list and only cancels the first one. The self-removal behavior of the work only happens after the handler has returned. This yields a situations where the reqlist can have two reqs for the same "handle" but rdmaaddrcancel() only cancels the first one.
The second req remains active beyond rdmadestroyid() and will use-after-free idpriv once it inevitably triggers.
Fix this by remembering if the idpriv has called rdmaresolveip() and always cancel before calling it again. This ensures the reqlist never gets more than one item in it and doesn't cost anything in the normal flow that never uses this strange error path.
In the Linux kernel, the following vulnerability has been resolved:
ASoC: max9759: fix underflow in speakergaincontrolput()
Check for negative values of "priv->gain" to prevent an out of bounds access. The concern is that these might come from the user via: -> sndctlelemwriteuser() -> sndctlelemwrite() -> kctl->put()
In the Linux kernel, the following vulnerability has been resolved:
iio: buffer: Fix file related error handling in IIOBUFFERGETFDIOCTL
If we fail to copy the just created file descriptor to userland, we try to clean up by putting back 'fd' and freeing 'ib'. The code uses putunusedfd() for the former which is wrong, as the file descriptor was already published by fdinstall() which gets called internally by anoninodegetfd().
This makes the error handling code leaving a half cleaned up file descriptor table around and a partially destructed 'file' object, allowing userland to play use-after-free tricks on us, by abusing the still usable fd and making the code operate on a dangling 'file->privatedata' pointer.
Instead of leaving the kernel in a partially corrupted state, don't attempt to explicitly clean up and leave this to the process exit path that'll release any still valid fds, including the one created by the previous call to anoninodegetfd(). Simply return -EFAULT to indicate the error.
In the Linux kernel, the following vulnerability has been resolved:
net: avoid potential UAF in defaultoperstate()
syzbot reported an UAF in defaultoperstate() [1]
Issue is a race between device and netns dismantles.
After calling rtnlunlock() from netdevruntodo(), we can not assume the netns of each device is still alive.
Make sure the device is not in NETREGUNREGISTERED state, and add an ASSERTRTNL() before the call to devgetbyindex().
We might move this ASSERTRTNL() in devgetbyindex() in the future.
[1]
BUG: KASAN: slab-use-after-free in devgetbyindex+0x5d/0x110 net/core/dev.c:852 Read of size 8 at addr ffff888043eba1b0 by task syz.0.0/5339
CPU: 0 UID: 0 PID: 5339 Comm: syz.0.0 Not tainted 6.12.0-syzkaller-10296-gaaf20f870da0 #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 Call Trace: <TASK> dumpstack lib/dumpstack.c:94 [inline] dumpstacklvl+0x241/0x360 lib/dumpstack.c:120 printaddressdescription mm/kasan/report.c:378 [inline] printreport+0x169/0x550 mm/kasan/report.c:489 kasanreport+0x143/0x180 mm/kasan/report.c:602 devgetbyindex+0x5d/0x110 net/core/dev.c:852 defaultoperstate net/core/linkwatch.c:51 [inline] rfc2863policy+0x224/0x300 net/core/linkwatch.c:67 linkwatchdodev+0x3e/0x170 net/core/linkwatch.c:170 netdevruntodo+0x461/0x1000 net/core/dev.c:10894 rtnlunlock net/core/rtnetlink.c:152 [inline] rtnlnetunlock include/linux/rtnetlink.h:133 [inline] rtnldellink+0x760/0x8d0 net/core/rtnetlink.c:3520 rtnetlinkrcvmsg+0x791/0xcf0 net/core/rtnetlink.c:6911 netlinkrcvskb+0x1e3/0x430 net/netlink/afnetlink.c:2541 netlinkunicastkernel net/netlink/afnetlink.c:1321 [inline] netlinkunicast+0x7f6/0x990 net/netlink/afnetlink.c:1347 netlinksendmsg+0x8e4/0xcb0 net/netlink/afnetlink.c:1891 socksendmsgnosec net/socket.c:711 [inline] socksendmsg+0x221/0x270 net/socket.c:726 syssendmsg+0x52a/0x7e0 net/socket.c:2583 syssendmsg net/socket.c:2637 [inline] syssendmsg+0x269/0x350 net/socket.c:2669 dosyscallx64 arch/x86/entry/common.c:52 [inline] dosyscall64+0xf3/0x230 arch/x86/entry/common.c:83 entrySYSCALL64afterhwframe+0x77/0x7f RIP: 0033:0x7f2a3cb80809 Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f2a3d9cd058 EFLAGS: 00000246 ORIGRAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f2a3cd45fa0 RCX: 00007f2a3cb80809 RDX: 0000000000000000 RSI: 0000000020000000 RDI: 0000000000000008 RBP: 00007f2a3cbf393e R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f2a3cd45fa0 R15: 00007ffd03bc65c8 </TASK>
Allocated by task 5339: kasansavestack mm/kasan/common.c:47 [inline] kasansavetrack+0x3f/0x80 mm/kasan/common.c:68 poisonkmallocredzone mm/kasan/common.c:377 [inline] kasankmalloc+0x98/0xb0 mm/kasan/common.c:394 kasankmalloc include/linux/kasan.h:260 [inline] kmalloccachenoprof+0x243/0x390 mm/slub.c:4314 kmallocnoprof include/linux/slab.h:901 [inline] kmallocarraynoprof include/linux/slab.h:945 [inline] netdevcreatehash net/core/dev.c:11870 [inline] netdevinit+0x10c/0x250 net/core/dev.c:11890 opsinit+0x31e/0x590 net/core/netnamespace.c:138 setupnet+0x287/0x9e0 net/core/netnamespace.c:362 copynetns+0x33f/0x570 net/core/netnamespace.c:500 createnewnamespaces+0x425/0x7b0 kernel/nsproxy.c:110 unsharensproxynamespaces+0x124/0x180 kernel/nsproxy.c:228 ksysunshare+0x57d/0xa70 kernel/fork.c:3314 dosysunshare kernel/fork.c:3385 [inline] sesysunshare kernel/fork.c:3383 [inline] x64sysunshare+0x38/0x40 kernel/fork.c:3383 dosyscallx64 arch/x86/entry/common.c:52 [inline] dosyscall64+0xf3/0x230 arch/x8 ---truncated---
In the Linux kernel, the following vulnerability has been resolved:
net: hns3: fixed hclgefetchpfreg accesses bar space out of bounds issue
The TQP BAR space is divided into two segments. TQPs 0-1023 and TQPs 1024-1279 are in different BAR space addresses. However, hclgefetchpfreg does not distinguish the tqp space information when reading the tqp space information. When the number of TQPs is greater than 1024, access bar space overwriting occurs. The problem of different segments has been considered during the initialization of tqp.iobase. Therefore, tqp.iobase is directly used when the queue is read in hclgefetchpfreg.
The error message:
Unable to handle kernel paging request at virtual address ffff800037200000 pc : hclgefetchpfreg+0x138/0x250 [hclge] lr : hclgegetregs+0x84/0x1d0 [hclge] Call trace: hclgefetchpfreg+0x138/0x250 [hclge] hclgegetregs+0x84/0x1d0 [hclge] hns3getregs+0x2c/0x50 [hns3] ethtoolgetregs+0xf4/0x270 devethtool+0x674/0x8a0 devioctl+0x270/0x36c sockdoioctl+0x110/0x2a0 sockioctl+0x2ac/0x530 arm64sysioctl+0xa8/0x100 invokesyscall+0x4c/0x124 el0svccommon.constprop.0+0x140/0x15c doel0svc+0x30/0xd0 el0svc+0x1c/0x2c el0synchandler+0xb0/0xb4 el0sync+0x168/0x180
In the Linux kernel, the following vulnerability has been resolved:
KVM: x86/mmu: Zap all roots when unmapping gfn range in TDP MMU
Zap both valid and invalid roots when zapping/unmapping a gfn range, as KVM must ensure it holds no references to the freed page after returning from the unmap operation. Most notably, the TDP MMU doesn't zap invalid roots in mmunotifier callbacks. This leads to use-after-free and other issues if the mmunotifier runs to completion while an invalid root zapper yields as KVM fails to honor the requirement that there must be no references to the page after the mmunotifier returns.
The bug is most easily reproduced by hacking KVM to cause a collision between setnxhugepages() and kvmmmunotifierrelease(), but the bug exists between kvmmmunotifierinvalidaterangestart() and memslot updates as well. Invalidating a root ensures pages aren't accessible by the guest, and KVM won't read or write page data itself, but KVM will trigger e.g. kvmsetpfndirty() when zapping SPTEs, and thus completing a zap of an invalid root after the mmunotifier returns is fatal.
WARNING: CPU: 24 PID: 1496 at arch/x86/kvm/../../../virt/kvm/kvmmain.c:173 [kvm] RIP: 0010:kvmiszonedevicepfn+0x96/0xa0 [kvm] Call Trace: <TASK> kvmsetpfndirty+0xa8/0xe0 [kvm] handlechangedspte+0x2ab/0x5e0 [kvm] handlechangedspte+0x2ab/0x5e0 [kvm] handlechangedspte+0x2ab/0x5e0 [kvm] zapgfnrange+0x1f3/0x310 [kvm] kvmtdpmmuzapinvalidatedroots+0x50/0x90 [kvm] kvmmmuzapallfast+0x177/0x1a0 [kvm] setnxhugepages+0xb4/0x190 [kvm] paramattrstore+0x70/0x100 moduleattrstore+0x19/0x30 kernfsfopwriteiter+0x119/0x1b0 newsyncwrite+0x11c/0x1b0 vfswrite+0x1cc/0x270 ksyswrite+0x5f/0xe0 dosyscall64+0x38/0xc0 entrySYSCALL64afterhwframe+0x44/0xae </TASK>
In the Linux kernel, the following vulnerability has been resolved:
powerpc/pseries: Fix use after free in removephbdynamic()
In removephbdynamic() we use &phb->ioresource, after we've called deviceunregister(&hostbridge->dev). But the unregister may have freed phb, because pcibiosfreecontrollerdeferred() is the release function for the hostbridge.
If there are no outstanding references when we call deviceunregister() then phb will be freed out from under us.
This has gone mainly unnoticed, but with slubdebug and pagepoison enabled it can lead to a crash:
PID: 7574 TASK: c0000000d492cb80 CPU: 13 COMMAND: "drmgr" #0 [c0000000e4f075a0] crashkexec at c00000000027d7dc #1 [c0000000e4f075d0] oopsend at c000000000029608 #2 [c0000000e4f07650] badpagefault at c0000000000904b4 #3 [c0000000e4f076c0] dobadslbfault at c00000000009a5a8 #4 [c0000000e4f076f0] dataaccessslbcommonvirt at c000000000008b30 Data SLB Access [380] exception frame: R0: c000000000167250 R1: c0000000e4f07a00 R2: c000000002a46100 R3: c000000002b39ce8 R4: 00000000000000c0 R5: 00000000000000a9 R6: 3894674d000000c0 R7: 0000000000000000 R8: 00000000000000ff R9: 0000000000000100 R10: 6b6b6b6b6b6b6b6b R11: 0000000000008000 R12: c00000000023da80 R13: c0000009ffd38b00 R14: 0000000000000000 R15: 000000011c87f0f0 R16: 0000000000000006 R17: 0000000000000003 R18: 0000000000000002 R19: 0000000000000004 R20: 0000000000000005 R21: 000000011c87ede8 R22: 000000011c87c5a8 R23: 000000011c87d3a0 R24: 0000000000000000 R25: 0000000000000001 R26: c0000000e4f07cc8 R27: c00000004d1cc400 R28: c0080000031d00e8 R29: c00000004d23d800 R30: c00000004d1d2400 R31: c00000004d1d2540 NIP: c000000000167258 MSR: 8000000000009033 OR3: c000000000e9f474 CTR: 0000000000000000 LR: c000000000167250 XER: 0000000020040003 CCR: 0000000024088420 MQ: 0000000000000000 DAR: 6b6b6b6b6b6b6ba3 DSISR: c0000000e4f07920 Syscall Result: fffffffffffffff2 [NIP : releaseresource+56] [LR : releaseresource+48] #5 [c0000000e4f07a00] releaseresource at c000000000167258 (unreliable) #6 [c0000000e4f07a30] removephbdynamic at c000000000105648 #7 [c0000000e4f07ab0] dlparremoveslot at c0080000031a09e8 [rpadlpario] #8 [c0000000e4f07b50] removeslotstore at c0080000031a0b9c [rpadlpario] #9 [c0000000e4f07be0] kobjattrstore at c000000000817d8c #10 [c0000000e4f07c00] sysfskfwrite at c00000000063e504 #11 [c0000000e4f07c20] kernfsfopwriteiter at c00000000063d868 #12 [c0000000e4f07c70] newsyncwrite at c00000000054339c #13 [c0000000e4f07d10] vfswrite at c000000000546624 #14 [c0000000e4f07d60] ksyswrite at c0000000005469f4 #15 [c0000000e4f07db0] systemcallexception at c000000000030840 #16 [c0000000e4f07e10] systemcallvectoredcommon at c00000000000c168
To avoid it, we can take a reference to the hostbridge->dev until we're done using phb. Then when we drop the reference the phb will be freed.
In the Linux kernel, the following vulnerability has been resolved:
fbdev: defio: fix the pagelist corruption
Easily hit the below list corruption: == listadd corruption. prev->next should be next (ffffffffc0ceb090), but was ffffec604507edc8. (prev=ffffec604507edc8). WARNING: CPU: 65 PID: 3959 at lib/listdebug.c:26 listaddvalid+0x53/0x80 CPU: 65 PID: 3959 Comm: fbdev Tainted: G U RIP: 0010:listaddvalid+0x53/0x80 Call Trace: <TASK> fbdeferrediomkwrite+0xea/0x150 dopagemkwrite+0x57/0xc0 dowppage+0x278/0x2f0 handlemmfault+0xdc2/0x1590 handlemmfault+0xdd/0x2c0 douseraddrfault+0x1d3/0x650 excpagefault+0x77/0x180 ? asmexcpagefault+0x8/0x30 asmexcpagefault+0x1e/0x30 RIP: 0033:0x7fd98fc8fad1 ==
Figure out the race happens when one process is adding &page->lru into the pagelist tail in fbdeferrediomkwrite(), another process is re-initializing the same &page->lru in fbdeferrediofault(), which is not protected by the lock.
This fix is to init all the page lists one time during initialization, it not only fixes the list corruption, but also avoids INITLISTHEAD() redundantly.
V2: change "int i" to "unsigned int i" (Geert Uytterhoeven)
In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: Mark inode as bad as soon as error detected in mienumattr()
Extended the mienumattr() function interface with an additional parameter, struct ntfsinode ni, to allow marking the inode as bad as soon as an error is detected.
In the Linux kernel, the following vulnerability has been resolved:
btrfs: fix use-after-free on inode when scanning root during em shrinking
At btrfsscanroot() we are accessing the inode's root (and fsinfo) in a call to btrfsfsclosing() after we have scheduled the inode for a delayed iput, and that can result in a use-after-free on the inode in case the cleaner kthread does the iput before we dereference the inode in the call to btrfsfsclosing().
Fix this by using the fsinfo stored already in a local variable instead of doing inode->root->fsinfo.
In the Linux kernel, the following vulnerability has been resolved:
keys: Fix UAF in keyput()
Once a key's reference count has been reduced to 0, the garbage collector thread may destroy it at any time and so keyput() is not allowed to touch the key after that point. The most keyput() is normally allowed to do is to touch keygcwork as that's a static global variable.
However, in an effort to speed up the reclamation of quota, this is now done in keyput() once the key's usage is reduced to 0 - but now the code is looking at the key after the deadline, which is forbidden.
Fix this by using a flag to indicate that a key can be gc'd now rather than looking at the key's refcount in the garbage collector.
In the Linux kernel, the following vulnerability has been resolved:
mm/gup: reject FOLLSPLITPMD with hugetlb VMAs
Patch series "mm: fixes for device-exclusive entries (hmm)", v2.
Discussing the PageTail() call in makedeviceexclusiverange() with Willy, I recently discovered [1] that device-exclusive handling does not properly work with THP, making the hmm-tests selftests fail if THPs are enabled on the system.
Looking into more details, I found that hugetlb is not properly fenced, and I realized that something that was bugging me for longer -- how device-exclusive entries interact with mapcounts -- completely breaks migration/swapout/split/hwpoison handling of these folios while they have device-exclusive PTEs.
The program below can be used to allocate 1 GiB worth of pages and making them device-exclusive on a kernel with CONFIGTESTHMM.
Once they are device-exclusive, these folios cannot get swapped out (proc$pid/smapsrollup will always indicate 1 GiB RSS no matter how much one forces memory reclaim), and when having a memory block onlined to ZONEMOVABLE, trying to offline it will loop forever and complain about failed migration of a page that should be movable.
echo offline > /sys/devices/system/memory/memory136/state echo onlinemovable > /sys/devices/system/memory/memory136/state ./hmm-swap & ... wait until everything is device-exclusive echo offline > /sys/devices/system/memory/memory136/state [ 285.193431][T14882] page: refcount:2 mapcount:0 mapping:0000000000000000 index:0x7f20671f7 pfn:0x442b6a [ 285.196618][T14882] memcg:ffff888179298000 [ 285.198085][T14882] anon flags: 0x5fff0000002091c(referenced|uptodate| dirty|active|owner2|swapbacked|node=1|zone=3|lastcpupid=0x7ff) [ 285.201734][T14882] raw: ... [ 285.204464][T14882] raw: ... [ 285.207196][T14882] page dumped because: migration failure [ 285.209072][T14882] pageowner tracks the page as allocated [ 285.210915][T14882] page last allocated via order 0, migratetype Movable, gfpmask 0x140dca(GFPHIGHUSERMOVABLE|GFPCOMP|GFPZERO), id 14926, tgid 14926 (hmm-swap), ts 254506295376, freets 227402023774 [ 285.216765][T14882] postallochook+0x197/0x1b0 [ 285.218874][T14882] getpagefromfreelist+0x76e/0x3280 [ 285.220864][T14882] allocfrozenpagesnoprof+0x38e/0x2740 [ 285.223302][T14882] allocpagesmpol+0x1fc/0x540 [ 285.225130][T14882] folioallocmpolnoprof+0x36/0x340 [ 285.227222][T14882] vmaallocfolionoprof+0xee/0x1a0 [ 285.229074][T14882] handlemmfault+0x2b38/0x56a0 [ 285.230822][T14882] handlemmfault+0x368/0x9f0 ...
This series fixes all issues I found so far. There is no easy way to fix without a bigger rework/cleanup. I have a bunch of cleanups on top (some previous sent, some the result of the discussion in v1) that I will send out separately once this landed and I get to it.
I wish we could just use some special present PROTNONE PTEs instead of these (non-present, non-none) fake-swap entries; but that just results in the same problem we keep having (lack of spare PTE bits), and staring at other similar fake-swap entries, that ship has sailed.
With this series, makedeviceexclusive() doesn't actually belong into mm/rmap.c anymore, but I'll leave moving that for another day.
I only tested this series with the hmm-tests selftests due to lack of HW, so I'd appreciate some testing, especially if the interaction between two GPUs wanting a device-exclusive entry works as expected.
<program> #include <stdio.h> #include <fcntl.h> #include <stdint.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/ioctl.h>
#define HMMDMIRROREXCLUSIVE IOWR('H', 0x05, struct hmmdmirrorcmd)
struct hmmdmirrorcmd { u64 addr; u64 ptr; u64 npages; u64 cpages; u64 faults; };
const sizet size = 1 1024 1024 1024ul; const sizet chunksize = 2 1024 1024ul;
int m ---truncated---
codel: remove sch->q.qlen check before qdisctreereducebacklog()
In the Linux kernel, the following vulnerability has been resolved:
pdscore: remove write-after-free of clientid
A use-after-free error popped up in stress testing:
[Mon Apr 21 21:21:33 2025] BUG: KFENCE: use-after-free write in pdscauxbusdevdel+0xef/0x160 [pdscore] [Mon Apr 21 21:21:33 2025] Use-after-free write at 0x000000007013ecd1 (in kfence-#47): [Mon Apr 21 21:21:33 2025] pdscauxbusdevdel+0xef/0x160 [pdscore] [Mon Apr 21 21:21:33 2025] pdscremove+0xc0/0x1b0 [pdscore] [Mon Apr 21 21:21:33 2025] pcideviceremove+0x24/0x70 [Mon Apr 21 21:21:33 2025] devicereleasedriverinternal+0x11f/0x180 [Mon Apr 21 21:21:33 2025] driverdetach+0x45/0x80 [Mon Apr 21 21:21:33 2025] busremovedriver+0x83/0xe0 [Mon Apr 21 21:21:33 2025] pciunregisterdriver+0x1a/0x80
The actual device uninit usually happens on a separate thread scheduled after this code runs, but there is no guarantee of order of thread execution, so this could be a problem. There's no actual need to clear the clientid at this point, so simply remove the offending code.
In the Linux kernel, the following vulnerability has been resolved:
writeback: avoid use-after-free after removing device
When a disk is removed, bdiunregister gets called to stop further writeback and wait for associated delayed work to complete. However, wbinodewritebackend() may schedule bandwidth estimation dwork after this has completed, which can result in the timer attempting to access the just freed bdiwriteback.
Fix this by checking if the bdiwriteback is alive, similar to when scheduling writeback work.
Since this requires wb->worklock, and wbinodewritebackend() may get called from interrupt, switch wb->worklock to an irqsafe lock.
In the Linux kernel, the following vulnerability has been resolved:
espintcp: remove encap socket caching to avoid reference leak
The current scheme for caching the encap socket can lead to reference leaks when we try to delete the netns.
The reference chain is: xfrmstate -> enacpsk -> netns
Since the encap socket is a userspace socket, it holds a reference on the netns. If we delete the espintcp state (through flush or individual delete) before removing the netns, the reference on the socket is dropped and the netns is correctly deleted. Otherwise, the netns may not be reachable anymore (if all processes within the ns have terminated), so we cannot delete the xfrm state to drop its reference on the socket.
This patch results in a small (~2% in my tests) performance regression.
A GC-type mechanism could be added for the socket cache, to clear references if the state hasn't been used "recently", but it's a lot more complex than just not caching the socket.
coresight: prevent deactivate active config while enabling the config
In the Linux kernel, the following vulnerability has been resolved:
schhfsc: make hfscqlennotify() idempotent
hfscqlennotify() is not idempotent either and not friendly to its callers, like fqcodeldequeue(). Let's make it idempotent to ease qdisctreereducebacklog() callers' life:
1. updatevf() decreases cl->clnactive, so we can check whether it is non-zero before calling it.
2. eltreeremove() always removes RB node cl->elnode, but we can use RBEMPTYNODE() + RBCLEARNODE() to make it safe.
In the Linux kernel, the following vulnerability has been resolved:
powerpc/bpf: fix JIT code size calculation of bpf trampoline
archbpftrampolinesize() provides JIT size of the BPF trampoline before the buffer for JIT'ing it is allocated. The total number of instructions emitted for BPF trampoline JIT code depends on where the final image is located. So, the size arrived at with the dummy pass in archbpftrampolinesize() can vary from the actual size needed in archpreparebpftrampoline(). When the instructions accounted in archbpftrampolinesize() is less than the number of instructions emitted during the actual JIT compile of the trampoline, the below warning is produced:
WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpfjitcomp.c:981 archpreparebpftrampoline.isra.0+0xd2c/0xdcc
which is:
/ Make sure the trampoline generation logic doesn't overflow / if (image && WARNONONCE(&image[ctx->idx] > (u32 )rwimageend - BPFINSNSAFETY)) {
So, during the dummy pass, instead of providing some arbitrary image location, account for maximum possible instructions if and when there is a dependency with image location for JIT'ing.
In the Linux kernel, the following vulnerability has been resolved:
net/sched: Always pass notifications when child class becomes empty
Certain classful qdiscs may invoke their classes' dequeue handler on an enqueue operation. This may unexpectedly empty the child qdisc and thus make an in-flight class passive via qlennotify(). Most qdiscs do not expect such behaviour at this point in time and may re-activate the class eventually anyways which will lead to a use-after-free.
The referenced fix commit attempted to fix this behavior for the HFSC case by moving the backlog accounting around, though this turned out to be incomplete since the parent's parent may run into the issue too. The following reproducer demonstrates this use-after-free:
tc qdisc add dev lo root handle 1: drr tc filter add dev lo parent 1: basic classid 1:1 tc class add dev lo parent 1: classid 1:1 drr tc qdisc add dev lo parent 1:1 handle 2: hfsc def 1 tc class add dev lo parent 2: classid 2:1 hfsc rt m1 8 d 1 m2 0 tc qdisc add dev lo parent 2:1 handle 3: netem tc qdisc add dev lo parent 3:1 handle 4: blackhole
echo 1 | socat -u STDIN UDP4-DATAGRAM:127.0.0.1:8888 tc class delete dev lo classid 1:1 echo 1 | socat -u STDIN UDP4-DATAGRAM:127.0.0.1:8888
Since backlog accounting issues leading to a use-after-frees on stale class pointers is a recurring pattern at this point, this patch takes a different approach. Instead of trying to fix the accounting, the patch ensures that qdisctreereducebacklog always calls qlennotify when the child qdisc is empty. This solves the problem because deletion of qdiscs always involves a call to qdiscreset() and / or qdiscpurgequeue() which ultimately resets its qlen to 0 thus causing the following qdisctreereducebacklog() to report to the parent. Note that this may call qlennotify on passive classes multiple times. This is not a problem after the recent patch series that made all the classful qdiscs qlennotify() handlers idempotent.