In the Linux kernel, the following vulnerability has been resolved:
USB: serial: ioti: fix heap overflow in getmanufinfo()
getmanufinfo() reads le16tocpu(romdesc->Size) bytes from the device I2C EEPROM into a buffer allocated with kmallocobj(), which is sizeof(struct edgetimanufdescriptor) = 10 bytes.
The Size field comes from the device and is only validated (in checki2cimage()) to make sure the descriptor fits within TIMAXI2CSIZE (16384 bytes), not against the destination buffer size. A malicious USB device can therefore set Size to any value up to 16377, causing a heap overflow of up to 16367 bytes when plugged into a host running this driver.
validcsum() is called after readrom() and also iterates buffer[0..Size-1], compounding the out-of-bounds access.
Fix by rejecting descriptors with unexpected length before calling readrom().
[ johan: amend commit message; also check for short descriptors ]
In the Linux kernel, the following vulnerability has been resolved:
KVM: arm64: Take the SRCU lock for page table walks in fault injection and AT emulation
walks1() and kvmwalknesteds2() expect to be called while holding kvm->srcu to guard against memslot changes. While this is generally the case, kvmats12() and kvmfinds1desclevel() call into the respective walkers without taking kvm->srcu.
Fix by acquiring kvm->srcu prior to the table walk in both instances.
In the Linux kernel, the following vulnerability has been resolved:
zram: fix use-after-free in zrambvecwritepartial()
zramreadpage() picks the sync or async backing device read path based on whether the parent bio is NULL. zrambvecwritepartial() passes its parent bio down, so for ZRAMWB slots the read is dispatched asynchronously and zramreadpage() returns 0 while the bio is still in flight. The caller then runs memcpyfrombvec(), zramwritepage() and freepage() on the buffer, leaving the async read to write into a freed page.
zrambvecreadpartial() was switched to NULL in commit 4e3c87b9421d ("zram: fix synchronous reads") for the same reason; the writepartial counterpart was missed.
In the Linux kernel, the following vulnerability has been resolved:
xfrm: policy: fix use-after-free on inexact bin in xfrmpolicybyselctx()
Fix the race by pruning the bin while still holding xfrmpolicylock, before dropping it. Use xfrmpolicyinexactprunebin() directly since the lock is already held. The wrapper xfrmpolicyinexactprunebin() becomes unused and is removed.
Race:
CPU0 (XFRMMSGDELPOLICY) CPU1 (XFRMMSGNEWSPDINFO) ========================== ========================== xfrmpolicybyselctx(): spinlockbh(xfrmpolicylock) bin = xfrmpolicyinexactlookup() xfrmpolicyunlink(pol) spinunlockbh(xfrmpolicylock) xfrmpolicykill(ret) // wide window, lock not held xfrmhashrebuild(): spinlockbh(xfrmpolicylock) xfrmpolicyinexactflush(): kfreercu(bin) // bin freed spinunlockbh(xfrmpolicylock) xfrmpolicyinexactprunebin(bin) // UAF: bin is freed
In the Linux kernel, the following vulnerability has been resolved:
ipv6: mcast: Fix use-after-free when processing MLD queries
When processing an MLD query, a pointer to the multicast group address is retrieved when initially parsing the packet. This pointer is later dereferenced without being reloaded despite the fact that the skb header might have been reallocated following the pskbmaypull() calls, leading to a use-after-free [1].
Fix by copying the multicast group address when the packet is initially parsed.
[1] BUG: KASAN: slab-use-after-free in mldquerywork (net/ipv6/mcast.c:1512) Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118
Workqueue: mld mldquerywork Call Trace: <TASK> dumpstacklvl (lib/dumpstack.c:94 lib/dumpstack.c:120) printaddressdescription.constprop.0 (mm/kasan/report.c:378) printreport (mm/kasan/report.c:482) kasanreport (mm/kasan/report.c:595) mldquerywork (net/ipv6/mcast.c:1512) mldquerywork (net/ipv6/mcast.c:1563) processonework (kernel/workqueue.c:3314) workerthread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread (kernel/kthread.c:436) retfromfork (arch/x86/kernel/process.c:158) retfromforkasm (arch/x86/entry/entry64.S:245) </TASK>
[...]
Freed by task 118: kasansavestack (mm/kasan/common.c:57) kasansavetrack (mm/kasan/common.c:78) kasansavefreeinfo (mm/kasan/generic.c:584) kasanslabfree (mm/kasan/common.c:253 mm/kasan/common.c:285) kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566) pskbexpandhead (net/core/skbuff.c:2335) pskbpulltail (net/core/skbuff.c:2878 (discriminator 4)) mldquerywork (net/ipv6/mcast.c:1495 (discriminator 1)) mldquerywork (net/ipv6/mcast.c:1563) processonework (kernel/workqueue.c:3314) workerthread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread (kernel/kthread.c:436) retfromfork (arch/x86/kernel/process.c:158) retfromforkasm (arch/x86/entry/entry64.S:245)
In the Linux kernel, the following vulnerability has been resolved:
ipv4: restrict IPOPTSSRR and IPOPTLSRR options
This patch restricts setting Loose Source and Record Route (LSRR) and Strict Source and Record Route (SSRR) IP options to users with CAPNETRAW capability.
This prevents unprivileged applications from forcing packets to route through attacker-controlled nodes to leak TCP ISN and possibly other protocol information.
While LSRR and SSRR are commonly filtered in many network environments, they may still be supported and forwarded along some network paths.
RFC 7126 (Recommendations on Filtering of IPv4 Packets Containing IPv4 Options) recommend to drop these options in 4.3 and 4.4.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: conntrackirc: fix possible out-of-bounds read
When parsing fails after we've matched the command string we should bail out instead of trying to match a different command.
This helper should be deprecated, given prevalence of TLS I doubt it has any relevance in 2026.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: nftexthdr: fix register tracking for FPRESENT flag
nftexthdrinit() passes user-controlled priv->len to nftparseregisterstore(), which marks that many bytes in the register bitmap as initialized. However, when NFTEXTHDRFPRESENT is set, the eval paths write only 1 byte (nftregstore8) or 4 bytes (dest = 0 on TCP/DCCP error path). When len > 4, registers beyond the first are never written, retaining uninitialized stack data from nftregs.
Bail out if userspace requests too much data when FPRESENT is set.
In the Linux kernel, the following vulnerability has been resolved:
net: guard timestamp cmsgs to real error queue skbs
skbiserrqueue() treats PACKETOUTGOING as the sole marker for an skb from skerrorqueue. That assumption is not true for AFPACKET sockets: outgoing packet taps are also delivered to packet sockets with skb->pkttype == PACKETOUTGOING, but their skb->cb is owned by AFPACKET instead of struct sockexterrskb.
If such an skb is received with timestamping enabled, the generic timestamp cmsg path can read AFPACKET control-buffer state as sockexterrskb::optstats. With SORXQOVFL enabled, the packet drop counter overlaps optstats. An odd drop count makes the path emit SCMTIMESTAMPINGOPTSTATS with skb->len and skb->data. For non-linear skbs this copies past the linear head and can trigger hardened usercopy or disclose adjacent heap contents.
Keep skbiserrqueue() local to net/socket.c, but make it verify that the PACKETOUTGOING marker is paired with the sockrmemfree destructor installed by sockqueueerrskb(). AFPACKET receive skbs use normal receive ownership and no longer pass as error-queue skbs, while legitimate skerrorqueue entries keep the PACKETOUTGOING marker and sockrmemfree ownership.
In the Linux kernel, the following vulnerability has been resolved:
tcp: restrict SOATTACHFILTER to priv users
This patch restricts the use of SOATTACHFILTER (cBPF) on TCP sockets to users with CAPNETADMIN capability.
This blocks potential side-channel attack where an unprivileged application attaches a filter to leak TCP sequence/acknowledgment numbers.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: nfqueue: hold bridge skb->dev while queued
brpassframeup() rewrites skb->dev from the ingress port to the bridge master before queueing bridge LOCALIN packets. NFQUEUE only holds references on state.in/out and bridge physdevs, so a queued bridge packet can retain a freed bridge master in skb->dev until reinjection.
When the verdict is reinjected later, brnetifreceiveskb() re-enters the receive path with skb->dev still pointing at the freed bridge master, triggering a use-after-free.
Store skb->dev in the queue entry, hold a reference on it for the queue lifetime, and use the saved device when dropping queued packets during NETDEVDOWN handling.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: nflog: validate MAC header was set before dumping it
The fallback path of dumpmacheader() guards the MAC header access only with "skb->macheader != skb->networkheader", without checking skbmacheaderwasset(). When the MAC header is unset, macheader is 0xffff, so the test passes and skbmacheader(skb) returns skb->head + 0xffff, ~64 KiB past the buffer; the loop then reads dev->hardheaderlen bytes out of bounds into the kernel log.
This is reachable via the netdev logger: nflogunknownpacket() calls dumpmacheader() unconditionally, and an skb sent through AFPACKET with PACKETQDISCBYPASS reaches the egress hook with macheader still unset (devqueuexmit(), which would reset it, is bypassed).
Add the skbmacheaderwasset() check the ARPHRDETHER path already uses, and replace the open-coded MAC header length test with skbmacheaderlen(). Only skbs with an unset MAC header are affected; valid ones are dumped as before.
BUG: KASAN: slab-out-of-bounds in dumpmacheader (net/netfilter/nflogsyslog.c:831) Read of size 1 at addr ffff88800ea49d3f by task exploit/148 Call Trace: kasanreport (mm/kasan/report.c:595) dumpmacheader (net/netfilter/nflogsyslog.c:831) nflognetdevpacket (net/netfilter/nflogsyslog.c:938 net/netfilter/nflogsyslog.c:963) nflogpacket (net/netfilter/nflog.c:260) nftlogeval (net/netfilter/nftlog.c:60) nftdochain (net/netfilter/nftablescore.c:285) nftdochainnetdev (net/netfilter/nftchainfilter.c:307) nfhookslow (net/netfilter/core.c:619) nfhookdirectegress (net/packet/afpacket.c:257) packetxmit (net/packet/afpacket.c:280) packetsendmsg (net/packet/afpacket.c:3114) syssendto (net/socket.c:2265)
In the Linux kernel, the following vulnerability has been resolved:
net: skbuff: fix missing zerocopy reference in pskbcarve helpers
pskbcarveinsideheader() and pskbcarveinsidenonlinear() both copy the old skbsharedinfo header into a new buffer via memcpy(), which includes the destructorarg pointer (uarg) for MSGZEROCOPY skbs. Neither function calls netzcopyget() for the new shinfo, creating an unaccounted holder: every skbsharedinfo with destructorarg set will call skbzcopyclear() once when freed, but the corresponding netzcopyget() was never called for the new copy. Repeated calls drive uarg->refcnt to zero prematurely, freeing ubufinfomsgzc while TX skbs still hold live destructorarg pointers.
KASAN reports use-after-free on a freed ubufinfomsgzc:
BUG: KASAN: slab-use-after-free in skbreleasedata+0x77b/0x810 Read of size 8 at addr ffff88801574d3e8 by task poc/220
Call Trace: skbreleasedata+0x77b/0x810 kfreeskblistreason+0x13e/0x610 skbreleasedata+0x4cd/0x810 skskbreasondrop+0xf3/0x340 skbqueuepurgereason+0x282/0x440 rdstcpincfree+0x1e/0x30 rdsrecvmsg+0x354/0x1780 sysrecvmsg+0xdf/0x180
Allocated by task 219: msgzerocopyrealloc+0x157/0x7b0 tcpsendmsglocked+0x2892/0x3ba0
Freed by task 219: iprecverror+0x74a/0xb10 tcprecvmsg+0x475/0x530
The skb consuming the late access still referenced the same uarg via shinfo->destructorarg copied by pskbcarveinsidenonlinear() without a refcount bump. This has been verified to be reliably exploitable: a working proof-of-concept achieves full root privilege escalation from an unprivileged local user on a default kernel configuration.
The fix follows the pattern of pskbexpandhead() which has the same memcpy/cloned structure. For pskbcarveinsideheader(), netzcopyget() is placed after skborphanfrags() succeeds, so the orphan error path needs no cleanup. For pskbcarveinsidenonlinear(), netzcopyget() is placed after all failure points and just before skbreleasedata(), so no error path needs cleanup at all -- matching pskbexpandhead() more closely and avoiding the need for a balancing netzcopyput().
In the Linux kernel, the following vulnerability has been resolved:
net: gro: don't merge zcopy skbs
skbgroreceive() can currently copy frags between the source and GRO skb, without checking the zerocopy status, and in particular the SKBFLMANAGEDFRAGREFS flag.
When SKBFLMANAGEDFRAGREFS is set, the skb doesn't hold a reference on the pages in shinfo->frags. Appending those frags to another skb's frags without fixing up the page refcount can lead to UAF.
When either the last skb in the GRO chain (the one we would append frags to) or the source skb is zerocopy, don't merge the skbs.
Fragnesia is a universal Linux local privilege escalation exploit, discovered by William Bowling with the V12 team. Fragnesia is a member of the Dirty Frag vulnerability class. This is a separate bug in the ESP/XFRM from dirtyfrag which has received its own patch. However, it is in the same surface and the mitigation is the same as for dirtyfrag.
It abuses a logic bug in the Linux XFRM ESP-in-TCP subsystem to achieve arbitrary byte writes into the kernel page cache of read-only files, without requiring any race condition.
The technique extends the page-cache write bug class that includes Dirty Pipe: when a TCP socket transitions to espintcp ULP mode after data has already been spliced from a file into the receive queue, the kernel processes the queued file pages as ESP ciphertext. The AES-GCM keystream byte at counter block position 2, byte 0 is XORed directly into the cached file page. By selecting the IV nonce to produce a desired keystream byte, any target byte in the file can be set to any value — one byte per trigger invocation.
The exploit builds a 256-entry lookup table mapping each possible keystream byte to its corresponding nonce, then iterates over a payload, firing the splice/ULP race for each byte that needs changing. It writes a small position-independent ELF stub (setresuid/setresgid/execve /bin/sh) over the first 192 bytes of /usr/bin/su in the page cache, then calls execve("/usr/bin/su") to obtain a root shell. The page cache modification is not backed to disk; the on-disk binary is untouched.
exit: prevent preemption of oopsing TASKDEAD task
In the Linux kernel, the following vulnerability has been resolved:
In the Linux kernel, the following vulnerability has been resolved:
x86/CPU/AMD: Prevent improper isolation of shared resources in Zen2's op cache
Make sure resources are not improperly shared in the op cache and cause instruction corruption this way.
In the Linux kernel, the following vulnerability has been resolved:
ipc: limit nextid allocation to the valid ID range
The checkpoint/restore sysctl path can request the next SysV IPC id through ids->nextid. ipcidralloc() currently forwards that request to idralloc() with an open-ended upper bound.
If the valid tail of the SysV IPC id space is full, the allocation can spill beyond ipcmni. The returned SysV IPC id still uses the normal index encoding, so later lookup and removal can target the wrong slot. This leaves the real IDR entry behind and breaks the IDR state for the object.
The bug is in ipcidralloc() in the checkpoint/restore path.
1. ids->nextid is passed to:
idralloc(&ids->ipcsidr, new, ipcidtoidx(nextid), 0, ...)
2. The zero upper bound makes the allocation effectively open-ended. Once the valid SysV IPC tail is occupied, idralloc() can spill past ipcmni and allocate an entry beyond the valid IPC id range.
3. The new object id is still encoded with the narrower SysV IPC index width:
new->id = (new->seq << ipcmniseqshift()) + idx
4. Later removal goes through ipcrmid(), which uses:
ipcidtoidx(ipcp->id)
That truncates the real IDR index. An object actually stored at a high index can then be removed as if it lived at a low in-range index.
5. For shared memory, shmdestroy() frees the current object anyway, but the real high IDR slot is left behind as a dangling pointer.
6. A subsequent walk of /proc/sysvipc/shm reaches the stale IDR entry and dereferences freed memory.
Prevent this by bounding the requested allocation to ipcmni so the checkpoint/restore path fails once the valid range is exhausted.
In the Linux kernel, the following vulnerability has been resolved:
riscv: Fix register corruption from uninitialized cregs on error
compatriscvgprset() calls cregstoregs() unconditionally, even when userregsetcopyin() fails. Since cregs is an uninitialized stack variable, a copyin failure causes uninitialized stack data to be written into the target task's ptregs, corrupting its register state and potentially leaking kernel stack contents.
compatrestoresigcontext() has the same issue: it calls cregstoregs() even when copyfromuser() fails, leading to the same corruption of the signal-returning task's register state on error.
Only call cregstoregs() when the user copy succeeds.
In the Linux kernel, the following vulnerability has been resolved:
hwmon: (pmbus/adm1266) include PEC byte in pmbusblockxfer read buffer
adm1266pmbusblockxfer() sets up the read transaction with
.buf = data->readbuf, .len = ADM1266PMBUSBLOCKMAX + 2,
but readbuf in struct adm1266data is declared as
u8 readbuf[ADM1266PMBUSBLOCKMAX + 1];
For a max-length block response (length byte = 255 + up to 1 PEC byte), the i2c controller is told to write 257 bytes into a 256-byte buffer, putting one byte past the end of readbuf. The same response also makes the subsequent PEC compare
if (crc != msgs[1].buf[msgs[1].buf[0] + 1])
read a byte beyond the array.
Bump the readbuf declaration to ADM1266PMBUSBLOCKMAX + 2 so the buffer can hold the length byte, up to 255 payload bytes, and the PEC byte the i2cmsg length already accounts for.
In the Linux kernel, the following vulnerability has been resolved:
nvme-pci: fix use-after-free in nvmefreehostmem()
nvmefreehostmem() frees dev->hmbsgt via dmafreenoncontiguous() but never clears the pointer afterward. This leads to a use-after-free if nvmefreehostmem() is called twice in the same error path.
This can happen during nvmeprobe() when nvmesetuphostmem() succeeds in allocating the HMB (setting dev->hmbsgt) but nvmesethostmem() fails with an I/O error:
nvmesetuphostmem() nvmeallochostmemsingle() -> sets dev->hmbsgt nvmesethostmem() -> fails with -EIO nvmefreehostmem() -> frees hmbsgt, but does NOT NULL it return error
nvmeprobe() error path: nvmefreehostmem() -> dev->hmbsgt is stale, use-after-free
The second call dereferences the freed sgt, causing a NULL pointer dereference in iommudmafreenoncontiguous() when it accesses sgt->sgl->dmaaddress (the backing memory has been freed and zeroed).
This is reproducible on Thunderbolt-attached NVMe devices (e.g., OWC Envoy Express behind a Dell WD22TB4 dock) where the device intermittently returns I/O errors during HMB setup due to PCIe link instability.
BUG: kernel NULL pointer dereference, address: 0000000000000010 RIP: 0010:iommudmafreenoncontiguous+0x22/0x80 Call Trace: <TASK> dmafreenoncontiguous+0x3b/0x130 nvmefreehostmem+0x30/0xf0 [nvme] nvmeprobe.cold+0xcc/0x275 [nvme] localpciprobe+0x43/0xa0 pcideviceprobe+0xeea/0x290 reallyprobe+0xf9/0x3b0 driverprobedevice+0x8b/0x170 driverprobedevice+0x24/0xd0 driverattachasynchelper+0x6b/0x110 asyncrunentryfn+0x37/0x170 processonework+0x1ac/0x3d0 workerthread+0x1b8/0x360 kthread+0xf7/0x130 retfromfork+0x2d8/0x3a0 retfromforkasm+0x1a/0x30 </TASK>
Fix this by setting dev->hmbsgt to NULL after freeing it, so the second call takes the multi-descriptor path which safely handles the already-cleaned-up state.
In the Linux kernel, the following vulnerability has been resolved:
irqwork: Fix use-after-free in irqworksingle() on PREEMPTRT
On PREEMPTRT, non-HARD irqwork runs in per-CPU kthreads via runirqworkd(), so irqworksync() uses rcuwait() to wait for BUSY==0.
After irqworksingle() clears BUSY via atomiccmpxchg(), it still dereferences @work for irqworkishard() and rcuwaitwakeup().
An irqworksync() caller on another CPU that enters after BUSY is cleared can observe BUSY==0 immediately, return, and free the work before those accesses complete — causing a use-after-free.
Fix this by wrapping runirqworkd() in guard(rcu)() so that the entire irqworksingle() execution is within an RCU read-side critical section. Then add synchronizercu() in irqworksync() after rcuwaitwaitevent() to ensure the caller waits for the RCU grace period before returning, preventing premature frees.
In the Linux kernel, the following vulnerability has been resolved:
fs/statmount: fix slab out-of-bounds write in statmountmntidmap
statmountmntidmap() writes one mapping with seqprintf() and then manually advances seq->count to include the NUL separator.
If seqprintf() overflows, seqsetoverflow() sets seq->count to seq->size. The manual seq->count++ changes this to seq->size + 1. seqhasoverflowed() then no longer detects the overflow. The corrupted count returns to statmountstring(), which later executes:
seq->buf[seq->count++] = '\0';
This causes a 1-byte NULL out-of-bounds write on the dynamically allocated seq buffer.
Fix this by checking for overflow immediately after seqprintf().
In the Linux kernel, the following vulnerability has been resolved:
fprobe: Fix unregisterfprobe() to wait for RCU grace period
Commit 4346ba1604093 ("fprobe: Rewrite fprobe on function-graph tracer") changed fprobe to register struct fprobe to an rcu-hlist, but it forgot to wait for RCU GP. Thus there can be use-after-free if the fprobe is released right after unregistering. This can be happened on fprobe event and sample module code.
To fix this issue, add synchronizercu() in unregisterfprobe().
Note that BPF is OK because fprobe is used as a part of bpfkprobemultilink. This unregisters its fprobe in bpfkprobemultilinkrelease() and it is deallocated via bpfkprobemultilinkdealloc(), which is invoked from bpflinkdeferdeallocrcugp() RCU callback.
For BPF, this also introduced unregisterfprobeasync() which does NOT wait for RCU grace priod.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: bridge: ebtables: close module init race
sashiko reports for unrelated patch: Does the core ebtables initialization in ebtables.c suffer from a similar race? Once nfregistersockopt() completes, the sockopts are exposed globally.
sockopt has to be registered last, just like in ip/ip6/arptables.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: ebtables: move to two-stage removal scheme
Like previous patches for xtables, follow same pattern in ebtables. We can't reuse xt helpers: ebttable struct layout is incompatible.
table->ops assignment is now done while still holding the ebt mutex to make sure we never expose partially-filled table struct.
In the Linux kernel, the following vulnerability has been resolved:
netfilter: xtables: add and use xtablesunregistertableexit
Previous change added xtablesunregistertablepreexit to detach the table from the packetpath and to unlink it from the active table list. In case of rmmod, userspace that is doing set/getsockopt for this table will not be able to re-instantiate the table: 1. The larval table has been removed already 2. existing instantiated table is no longer on the xt pernet table list.
This adds the second stage helper:
unlink the table from the dying list, free the hook ops (if any) and do the audit notification. It replaces xtunregistertable().
In the Linux kernel, the following vulnerability has been resolved:
firmware: armffa: Validate framework notification message layout
Framework notifications carry an indirect message in the shared RX buffer. Validate the reported offset and size before using them, reject zero-length payloads, and ensure that any non-header payload starts at the UUID field rather than in the middle of the message header.
Use the validated offset and size values for both kmemdup() and the UUID parsing path so malformed firmware data cannot drive an out-of-bounds read or an oversized allocation.
In the Linux kernel, the following vulnerability has been resolved:
hwmon: (pmbus/adm1266) cap PDIO scan in getmultiple at ADM1266PDIONR
adm1266gpiogetmultiple() iterates the PDIO portion of the caller-supplied mask using
foreachsetbitfrom(gpionr, mask, ADM1266GPIONR + ADM1266PDIOSTATUS) { ... }
where ADM1266PDIOSTATUS is the PMBus command code (0xE9, i.e. 233), not the number of PDIO pins. The intended upper bound is ADM1266GPIONR + ADM1266PDIONR = 25.
gpiolib hands in a mask sized for gc.ngpio (= 25 bits on this chip), so the iteration walks findnextbit() up to 242, reading up to 217 extra bits (a handful of unsigned-long words: four on 64-bit, seven on 32-bit) of whatever lives past the end of the mask in the caller's stack. Any incidental set bit in that range then drives a setbit(gpionr, bits) call that writes past the end of the caller-supplied bits array too -- both out-of-bounds.
Substitute ADM1266PDIONR for the constant so the scan stops at the last real PDIO bit.