Where
-Infinity
0
Severity
6.8
Integer Underflow
AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

The MCUmgr SMP-over-console transport decodes a base64 frame, reads a 16-bit packet length from it, verifies a CRC and then unconditionally strips the trailing CRC with rxctxt->nb->len -= 2U; in mcumgrserialprocessfrag() (subsys/mgmt/mcumgr/transport/src/serialutil.c). mcumgrserialextractlen() accepted any declared length, including 0 and 1, and a packet declaring length 0 passes the checksum test for free because crc16itut() over zero bytes returns the zero seed. Since netbuf::len is a uint16t, the subtraction underflows and the buffer is handed to SMP claiming roughly 65 KB of payload while its data area is only CONFIGMCUMGRTRANSPORTNETBUFSIZE bytes (default 384).

The trigger is a single unauthenticated 7-byte line on the management console — the 0x06 0x09 packet marker followed by the base64 group AAA= and a newline — delivered to any transport built on this helper: CONFIGMCUMGRTRANSPORTUART (smpuart.c) or CONFIGMCUMGRTRANSPORTSHELL (smpshell.c), both of which select MCUMGRTRANSPORTSERIALHASSMPOVERCONSOLE. No prior session state, fragmentation or credentials are required to trigger the underflow, and the malformed frame is mishandled before any command handler or command-level access control runs. The attacker only needs write access to that console, which on many boards is a USB CDC-ACM port rather than a bare UART header.

With the inflated length, smpprocessrequestpacket() in subsys/mgmt/mcumgr/smp/src/smp.c loses its bound: cbornbreaderinit() gives the CBOR decoder a ~65 KB window into a 384-byte buffer, and each request header's nhlen is checked only against the inflated length. On its own the 7-byte frame re-parses whatever stale bytes the reused pool buffer still holds, typically a replay of the previously received request followed by a parse error, without leaving the buffer. Because the transport is unauthenticated, though, the attacker also controls the frames sent before the trigger, and can stage buffer contents so that a request succeeds with an nhlen larger than the buffer; netbufpull(), guarded only by ASSERTNOMSG, then moves the parse cursor out of bounds and the loop reads further headers and CBOR from adjacent memory. The consequence is an out-of-bounds read that can fault the MCUmgr thread (denial of service); memory disclosure is also possible, since the default-enabled os echo handler (CONFIGMCUMGRGRPOSECHO) decodes its string inside that window and copies it into its response. There is no integrity gain beyond what the unauthenticated transport already permits.

The fix rejects any declared packet length of two bytes or fewer in mcumgrserialextractlen(), so the CRC-strip subtraction can no longer underflow. The identical pattern remains in the test-only loopback transport subsys/mgmt/mcumgr/transport/src/smpdummy.c (CONFIGMCUMGRTRANSPORTDUMMY), which has no external input path and therefore carries no practical exposure.

First published (updated )
Severity
6.5
AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

The native BSD-socket layer recorded a pending asynchronous socket error by type-punning it into struct netcontext's void userdata field (ctx->userdata = INTTOPOINTER(-status) in zsockacceptedcb(), zsockreceivedcb(), zsockconnectedcb() and zsockclosectx() in subsys/net/lib/sockets/socketsinet.c), reading it back with POINTERTOINT(). That same field is owned by the network stack for listening TCP contexts: nettcpaccept() stores the parent context pointer there and the TCP core passes it back to the registered accept callback. A failed accept therefore left a small integer (an errno value) where the stack expected a struct netcontext .

When the network interface carrying a listening TCP socket goes down, closetcpconn() in subsys/net/ip/tcp.c invokes the accept callback with -ENETDOWN and the context's userdata. In v4.3.0 the callback was not disarmed afterwards, so a second interface-down event forwarded the previously stored errno to zsockacceptedcb(), which dereferenced it as the parent context and performed several stores through it (sockseterror()'s read-modify-write of socketdata, kfifocancelwait(&parent->recvq)) — the crash described in the fix's commit message. v4.3.1 and v4.4.x carry a later change clearing conn->acceptcb after the error callback (269cb8823d3 on the v4.3 branch, 913fae5169425550f2364655298fceb79b320066 on main), which closes that repeat path; on those releases the poisoned cookie remains reachable only by a narrower race, a handshake completing alongside the interface-down still passing the stale cookie to kfifoput(&parent->acceptq, ...), and by getsockopt(SOERROR), which reads the field back unconditionally.

On v4.3.0 an application that keeps a listening TCP socket open across repeated link-down events is sufficient to reach the defect; the triggering condition is a network-interface state change, not attacker-supplied packet data, so the practical attacker is one able to force the link down repeatedly (for example an adjacent attacker disrupting a wireless link) or one with local/physical access. Because both the faulting address and the stored data are fixed small constants derived from the errno value, the outcome is a wild-pointer access leading to a kernel fatal error — a denial of service (device crash or reset) rather than an attacker-directed memory corruption.

The fix stores the pending error in a dedicated netcontext.sockerror field and converts every producer and consumer to sockseterror()/sockgeterror(), leaving userdata untouched. As a side effect it also stops getsockopt(SOERROR) — which is evaluated unconditionally — from returning the kernel address held in userdata to a userspace application.

First published (updated )
Severity
5.9
Null Pointer Dereference
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

parsewriteop() in subsys/net/lib/lwm2m/lwm2mmessagehandling.c handles inbound CoAP WRITE/CREATE requests that carry a Block1 option. For the first block of a transfer it called initblockctx() and then immediately stored the peer-selected block size with blockctx->ctx.blocksize = blocksize before inspecting the return code. initblockctx() sets the caller's pointer to NULL and returns -ENOMEM when no entry of the static block1contexts[] pool is free or timed out, so that store dereferences a NULL pointer.

The pool holds CONFIGLWM2MNUMBLOCK1CONTEXT entries (default 3) and an entry is only reclaimed once its transfer completes, fails, or ages past 30 seconds. A peer that reaches the client's LwM2M socket can therefore start three block-wise writes on three distinct object paths with the CoAP More bit set and leave them incomplete, then send the first block of a fourth write on a new path to reach the unguarded dereference. Reachability is gated only by the connected UDP socket's source-address filter unless CONFIGLWM2MDTLSSUPPORT is enabled — which has no default — so in a NoSec deployment an on-path or address-spoofing attacker needs no credentials; the same sequence is also reachable from a bootstrap or lower-trust server, and can be hit accidentally by a legitimate server running four concurrent block transfers.

The write targets a fixed low address with a value between 0 and 7, so the consequence is a fatal memory fault (BusFault or corrupted low memory leading to a fault) rather than a usable memory-corruption primitive: the device crashes or resets. Confidentiality and integrity are not affected. The fix moves the store below the guard and validates the context pointer itself instead of the return code, so the context is only touched once it is known to be valid.

First published (updated )
Severity
7.4
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:H

In Zephyr's WireGuard subsystem (subsys/net/lib/wireguard), wgprocessdatamessage() in wgcrypto.c linearizes an inbound transport-data payload into a fixed pool buffer of CONFIGWIREGUARDBUFLEN bytes before decryption. The call netbuflinearize(buf->data, datalen, pkt->buffer, ..., datalen) passed the attacker-derived datalen as both the destination capacity and the copy length, defeating the function's internal len = min(len, dstlen) bound. datalen is derived from the received UDP datagram length and is only lower-bounded by wgctrlrecv() (no upper bound). When datalen exceeds CONFIGWIREGUARDBUFLEN — e.g. when the buffer length is lowered below the link MTU, on links with MTU above the buffer size, or via reassembled IPv4/IPv6 fragments that exceed it — the underlying memcpy writes past the end of the pool buffer, an out-of-bounds write (CWE-787). The overflow occurs before the Poly1305 authentication check, so it requires only a valid receiver session index rather than a valid authenticator, and is reachable by a malicious or compromised peer (or an on-path attacker driving an established session) over the network, yielding remote memory corruption and at minimum a reliable denial of service. The defect was present in the WireGuard implementation shipped in Zephyr 4.4.0. The fix adds an explicit datalen > CONFIGWIREGUARDBUFLEN rejection and corrects the linearize call to pass netbufmaxlen(buf) as the destination capacity.

First published (updated )
Severity
5.3
Use After Free
AV:A/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H

Zephyr's native TCP stack iterates the global connection list in nettcpforeach() (subsys/net/ip/tcp.c) using the SYSSLISTFOREACHCONTAINERSAFE macro, which caches a pointer to the next list node. Prior to this fix the function released tcplock while invoking the per-connection callback and re-acquired it afterwards.

During that window a concurrent tcpconnrelease(), running on the dedicated TCP work-queue thread when a connection's reference count drops to zero (e.g. a remote peer closing or resetting the connection), can remove and kmemslabfree() the cached next connection. When the iterator advances it dereferences the freed (and possibly reallocated) slab memory — a use-after-free that can crash the system (denial of service) and, if the slot has been reused, cause the callback to operate on an attacker-influenced object (potential information disclosure or further fault).

nettcpforeach() is reached in production via the net conn network shell command and via nettcpcloseallforiface() on interface-down; the freeing side is driven by ordinary TCP traffic.

The fix moves the connection/context teardown in tcpconnrelease() inside the tcplock critical section and keeps tcplock held across the callback in nettcpforeach(). The defect was introduced with the modern (TCP2) stack in 2020 and affects releases up to and including v4.4.0.

First published (updated )
Severity
9.8
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

parseipv4() in subsys/net/ip/utils.c (reached via netipaddrparse() for strings of the form "a.b.c.d:port") copies the port substring into a fixed 17-byte stack buffer (char ipaddr[NETIPV4ADDRLEN + 1]) using a length of strlen - end - 1, where strlen is the full, unbounded input length and end is only the (<=15-byte) offset of the ':' delimiter. Because the destination size is never consulted, a crafted address string with a long suffix after the colon (e.g. "1.2.3.4:" followed by hundreds of bytes) causes an out-of-bounds stack write whose length and contents are fully attacker-controlled (memcpy of the suffix plus a trailing NUL), enabling memory corruption and at minimum a denial of service, and potentially control-flow hijack. The parser is reached from the standard socket API (zsockgetaddrinfo / literal-address resolution), DNS server-string configuration, and the eswifi Wi-Fi co-processor DNS-response path, so an application that resolves a network-influenced address string is exposed. The bug was introduced when the parser was added (Zephyr v1.9.0) and shipped in all releases through v4.4.0. The fix removes the unbounded copy and validates the port length before copying into a small dedicated buffer. Note: the equivalent IPv6 "[addr]:port" path in parseipv6() retains the same unbounded copy at this commit and remains a separate, still-reachable instance of the defect.

First published (updated )
Severity
9.8
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:H

dnsunpackname() caches the buffer tailroom once and reuses it while appending DNS labels. As the buffer grows, the cached size becomes incorrect, and the final null terminator can be written past the buffer. With assertions disabled (default), a malicious DNS response can trigger an out-of-bounds write when CONFIGDNSRESOLVER is enabled.

First published (updated )
Severity
9.1
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

The function dnscopyqname in dnspack.c performs performs a memcpy operation with an untrusted field and does not check if the source buffer is large enough to contain the copied data.

First published (updated )
Severity
6.8
AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

In DA, there is a possible out of bounds write due to a missing bounds check. This could lead to local escalation of privilege, if an attacker has physical access to the device, with no additional execution privileges needed. User interaction is needed for exploitation. Patch ID: ALPS09915215; Issue ID: MSV-3801.

First published (updated )
Severity
4.6
AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

In preloader, there is a possible read of device unique identifiers due to a logic error. This could lead to local information disclosure, if an attacker has physical access to the device, with no additional execution privileges needed. User interaction is not needed for exploitation. Patch ID: ALPS10607099; Issue ID: MSV-6118.

1 / 2
Source: NVD
First published (updated )
Severity
4.6
Divide by Zero
AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

The Zephyr ext2 file system validates the on-disk superblock in ext2verifydisksuperblock() (subsys/fs/ext2/ext2impl.c) before completing a mount. The validator checked the magic number, block size, revision and feature flags, but did not verify that the on-disk fields sblockspergroup and sinodespergroup are non-zero. Both fields are read directly from the image and are later used as divisors during mount-time initialization.

During mount, getngroups() divides and modulos sblockscount by sblockspergroup (reached via ext2fetchblockgroup() from ext2initfs()), and getitableentry() divides (ino - 1) by sinodespergroup when fetching the root inode (both in subsys/fs/ext2/ext2diskops.c). A superblock with either field set to zero therefore causes an integer division by zero during the mount sequence.

An attacker who can present a crafted ext2 image to a device that mounts ext2 — removable media such as an SD card or a USB mass-storage device — can trigger this. On ARMv7-M / ARMv8-M-mainline Cortex-M targets, divide-by-zero trapping is enabled (SCBCCRDIV0TRP), so the division raises a UsageFault that Zephyr treats as a fatal error, producing a denial of service. The impact is limited to availability; the malformed value is consumed only as a divisor.

The fix rejects a zero sblockspergroup or sinodespergroup in the superblock validator, returning -EINVAL so the mount fails before any block-group or inode I/O occurs.

First published (updated )
Severity
7.5
Path Traversal
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Zephyr's HTTP server (subsys/net/lib/http) provides a static-filesystem resource type (HTTPRESOURCETYPESTATICFS, available when CONFIGFILESYSTEM is enabled) that serves files from a configured root directory. Before this fix, both the HTTP/1 and HTTP/2 front-ends placed the raw, attacker-controlled request path into client->urlbuffer (assembled in onurl() for HTTP/1 and copied verbatim from the :path pseudo-header for HTTP/2) without resolving ./.. segments. The static-FS handler then built the on-disk filename by directly concatenating the configured root with that raw URL (snprintk(fname, ..., "%s%s", staticfsdetail->fspath, client->urlbuffer) at httpserverhttp1.c:603 and httpserverhttp2.c:490) and opened it with fsopen(fname, FSOREAD). Because the handler is reached via wildcard/leading-dir (fnmatch FNMLEADINGDIR) or fallback resource matching, a request such as GET /<prefix>/../../<file> is dispatched to the handler and, after the underlying filesystem (e.g. LittleFS/FAT) resolves the .. segments, escapes the configured web root, letting an unauthenticated remote client read arbitrary readable files on the mounted volume (information disclosure). The HTTP server requires no TLS or authentication to reach this path. The fix adds httpserverremovedotsegments(), which canonicalizes the path portion of the URL before resource lookup in both protocol handlers, neutralizing the traversal. Affects releases v4.0.0 through v4.4.0 for deployments that register a static-filesystem resource.

First published (updated )
Severity
8.1
AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

The IPv6 Neighbor Discovery handlers in subsys/net/ip/ipv6nbr.c (handlerainput, handlensinput, handlenainput) used an incorrect boolean expression that combined the RFC 4861 validity checks with the ICMPv6 code check using the wrong operator precedence: the form was ((length/hop/source/target checks) && (icmphdr->code != 0)). Because every legitimate ND message carries ICMPv6 code 0, an attacker setting code == 0 (the normal value) caused the entire predicate to evaluate false, so the packet was never dropped and all of the other checks were silently skipped. The bypassed checks include the mandatory Hop Limit == 255 verification (which proves an ND packet originated on-link and was not forwarded) and, for Router Advertisements, the requirement that the source be a link-local address, as well as multicast-target sanity checks. As a result, an adjacent on-link attacker — and, because the Hop-Limit-255 guard is bypassed, potentially a remote/off-link attacker whose packets would otherwise be rejected — can have forged Router Advertisement, Neighbor Solicitation, and Neighbor Advertisement messages accepted. A forged RA lets the attacker reconfigure the victim's default router, on-link prefixes (SLAAC), MTU, reachable/retransmit timers, and (with CONFIGNETIPV6RARDNSS) DNS servers, while forged NS/NA enable neighbor-cache poisoning, enabling man-in-the-middle, traffic redirection, and denial of service. The flaw is an input-validation/authentication weakness rather than a memory-safety issue: the underlying packet-parsing primitives (netpktgetdata, netpktread, netpktskip) are independently bounds-safe and the validated length is the true buffer length, so skipping the length check causes no out-of-bounds access. The defect has existed since the logic was introduced in 2018 and shipped in all releases through v4.4.0; it is fixed by splitting the condition so any failing check drops the packet.

First published (updated )
Severity
6.5
AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H

The CONFIGUSERSPACE syscall verifier zvrfykpoll() in kernel/poll.c allocates a kernel-side copy of the user-supplied kpollevent[] via zthreadmalloc() and then validates each event's object handle. Before this fix, validation used KOOPS(KSYSCALLOBJ(...)) inline inside the loop, which kills the calling thread without freeing eventscopy.

A user thread can pass numevents >= 1 with a forged object handle to leak the allocation; because newly spawned user threads inherit the parent's resourcepool (kernel/thread.c), an attacker spawns sacrificial threads to repeat the leak until the shared kernel heap is exhausted. Once depleted, legitimate kernel allocations from that pool (kqueue alloc nodes, kmsgq buffers, future kpoll calls, etc.) fail, causing a system-level denial of service.

The fix replaces each inline KOOPS with a conditional goto oopsfree so the buffer is freed before the thread is killed. Affects Zephyr releases from v1.12.0 (when kpoll was first exposed to user mode) through v4.4.1.

First published (updated )
Severity
7.4
AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:L

Zephyr's DNS resolver (subsys/net/lib/dns) parses resource records from DNS responses in dnsunpackanswer(), which validated only the fixed RR header (type, class, TTL, rdlength) and accepted any attacker-declared rdlength, including one extending past the end of the received datagram. The TXT and SRV consumers in dnsvalidaterecord() (resolve.c) then read up to rdlength bytes (clamped only to a record-type maximum such as DNSMAXTEXTSIZE, default 64, not to the packet) from the receive buffer via memcpy without their own bounds check, and pass the result to the application's resolve callback. A malicious or spoofed DNS server, an on-path attacker forging UDP DNS replies, or (with mDNS/LLMNR enabled) any LAN node can craft a truncated TXT or SRV response that causes an out-of-bounds read of adjacent receive-pool memory; the disclosed stale bytes (residual contents of prior DNS packets / uninitialized pool memory) are returned to the application as TXT/SRV record contents, an information leak, and may in some configurations cross the allocation boundary and fault, causing a denial of service. The read is bounded (~64 bytes for TXT, ~6 for SRV) and read-only (no write). The fix rejects any record whose declared rdata extends past dnsmsg->msgsize at the single chokepoint in dnsunpackanswer(). Affected: v4.3.0 and v4.4.0.

First published (updated )
Severity
7.6
Use After Free
AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H

The Zephyr Bluetooth GATT client CCC-write response handler gattwritecccrsp() in subsys/bluetooth/host/gatt.c invoked the application's params->subscribe() callback after it had already called params->notify(conn, params, NULL, 0).

Per the public GATT API, a notify callback with NULL data is the documented signal that the subscription has terminated and the btgattsubscribeparams struct may be freed or reused by the application; calling subscribe() on the struct afterwards is a use-after-free, including an indirect call through the freed params->subscribe function pointer.

The error branch is remotely (adjacent) reachable: a Zephyr device acting as a GATT client that calls btgattsubscribe() can be driven into this ordering when a connected GATT server peer answers the CCC write with an ATT Error Response (the peer-supplied error code flows through atterrorrsp -> atthandlersp into gattwritecccrsp).

For applications that free or recycle subscription parameters in their notification-termination handler, this results in memory corruption, a crash (denial of service), or potentially attacker-influenced control flow. The fix reorders the handler so the subscribe() callback runs before the terminating notify(NULL) in both the error and unsubscribe paths.

First published (updated )
Severity
4.6
AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

In the Synopsys DesignWare I2C driver (drivers/i2c/i2cdw.c) operating in target/slave mode, the rxfull interrupt handler gates the writerequested() callback on dw->state != CMDSEND, and dw->state is only reset to READY on a STOP interrupt. The STARTDET interrupt, whose handler in i2cdwslavereadclearintrbits() would reset the state on every (re)START, was never added to the enabled interrupt mask in i2cdwslaveregister(), so that recovery path was dead code.

As a result, if the STOP interrupt is lost (bus glitch/reset, or a concurrent master driving STOP) or the bus master issues a legal WRITE-repeated-START-WRITE sequence with the same direction, the driver remains in CMDSEND permanently and never invokes writerequested() again for the life of the target.

An I2C master on the same physical bus can deliberately trigger this, causing the I2C target function to malfunction for all subsequent write transactions and desynchronizing consumer framing state (e.g. MCTP-over-I2C), a recoverable-by-reset denial of service of the target peripheral.

The fix unmasks STARTDET so the state is reset at every bus (re)START. Impact is availability-only over a local board-level bus; no memory corruption results in the in-tree consumer, whose per-byte buffer write is independently bounds-checked.

First published (updated )
Severity
7.1
AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

btisorecv() in subsys/bluetooth/host/iso.c pulled the ISO SDU header (4 bytes) or, when the timestamp flag is set, the timestamped SDU header (8 bytes) from the inbound HCI ISO Data buffer via netbufpullmem() without first checking buf->len. The upstream hciiso() handler enforces buf->len == the controller-declared ISO DataLoad length, so a malicious or buggy controller / adjacent BLE peer on an established CIS/BIS can present a first-fragment (BTISOSTART) or single (BTISOSINGLE) PDU shorter than the SDU header. Because netbufsimplepullmem only guards length with ASSERTNOMSG (compiled out when CONFIGASSERT is disabled, the production default), the pull underflows buf->len (uint16t, e.g. 0 - 8 = 0xFFF8) and advances buf->data past valid data: the subsequent reads of hdr->slen and hdr->sn are out-of-bounds reads of adjacent pool memory. For the multi-fragment (START) case the corrupted buffer is retained as iso->rx, and a following CONT/END fragment's netbuftailroom() guard underflows to a near-SIZEMAX value, defeating the bounds check and causing netbufaddmem() to memcpy attacker-supplied fragment data far past the RX pool buffer (out-of-bounds write). The flaw affects ISO receive builds (CONFIGBTISORX, selected by the default-off LE Audio options BTISOPERIPHERAL/BTISOCENTRAL/BTISOSYNCRECEIVER) and has existed since the ISO subsystem was introduced (v2.6.0) through v4.4.0. The fix adds explicit buf->len < sizeof(tshdr) and buf->len < sizeof(hdr) checks that drop the buffer before pulling.

First published (updated )
Severity
9.1
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L

subsys/net/lib/lwm2m/lwm2mpullcontext.c copied the firmware-update Package URI into a fixed static buffer (context.uri, size CONFIGLWM2MSWMGMTPACKAGEURILEN, default 128) with memcpy(context.uri, uri, LWM2MPACKAGEURILEN), copying exactly the destination size with no length validation. The Firmware-Update object stores the server-supplied Package URI (/5/0/1) in a 255-byte buffer, so a LwM2M management server (or an on-path attacker on a session lacking strong DTLS) can WRITE a URI of 128-254 characters; only the first 128 bytes are then copied into context.uri with no NUL terminator. That buffer is subsequently consumed as a C string by httpparserparseurl(context.uri, strlen(context.uri), ...), strlen-based CoAP URI-path/PROXY-URI option appends, and lwm2mparsepeerinfo(), causing an out-of-bounds read of adjacent static memory. The over-read bytes are appended to outbound CoAP requests (information disclosure of adjacent device memory to the server/proxy) and can crash the device (denial of service). The vulnerable copy was introduced by the pull-context refactor (first released in v3.0.0) and is present through v4.4.0; the default-on CONFIGLWM2MFIRMWAREUPDATEPULLSUPPORT path is affected. The fix adds a strlen(uri) >= sizeof(context.uri) check returning -ENOMEM and switches to strcpy(), guaranteeing a bounded, NUL-terminated buffer.

First published (updated )
Severity
5.3
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L

Zephyr's DNS resolver detects mDNS (.local) queries in dnsresolvenameinternal() (subsys/net/lib/dns/resolve.c) with memcmp(strrchr(query, '.'), ".local", 7), which always reads a fixed 7 bytes from the suffix pointer. When the resolved hostname's final label is shorter than 7 bytes (e.g. names ending in .org, .com, .net, .io, or a trailing dot), the comparison reads 1-2 bytes past the string's NUL terminator.

The hostname (query) is the caller-supplied name passed through the standard getaddrinfo()/dnsgetaddrinfo()/dnsresolvename() path and is influenceable by operators or remote inputs (server names from configuration, parsed URLs, or app-facing interfaces).

On a tightly-sized buffer with no slack (for example a userspace getaddrinfo call where the hostname is copied with kusermodestringalloccopy to exactly strlen+1 bytes), the over-read crosses the allocation boundary; if that boundary is unmapped (guard page, memory-domain boundary under MPU, or an address sanitizer) the over-read faults, causing a denial of service. The over-read bytes are never returned, so there is no information disclosure.

The flaw is compiled only when CONFIGMDNSRESOLVER is enabled, exists since v1.10.0, and is fixed by replacing the fixed-length memcmp with a NUL-safe strcmp(ptr, ".local").

First published (updated )
Severity
7.8
Use After Free
AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H

Zephyr's dynamic kernel-object tracking (kernel/userspace/userspace.c, formerly kernel/userspace.c) maintains a doubly-linked list (objlist) of dynamically allocated kernel objects. Iteration over this list in kobjectwordlistforeach() was performed under listslock using the SAFE iterator (which caches the next node), but list removal and freeing of nodes was performed under different, disjoint spinlocks: objfreelock in kobjectfree() and objlock in unrefcheck(). On an SMP system, while one CPU iterated objlist under listslock, another CPU could unlink and kfree() the dynobj node that the iterator had cached as its next pointer, causing the iterator to dereference freed kernel memory (use-after-free / dangling list traversal). All of the racing operations are reachable from unprivileged user-mode threads via system calls: kobjectalloc/kobjectallocsize and kobjectrelease drive removals through unrefcheck() (under objlock), while kthreadabort and thread creation drive the iteration through kthreadpermsallclear()/kthreadpermsinherit() (under listslock). A deprivileged user thread on a CONFIGSMP + CONFIGUSERSPACE build can therefore corrupt the kernel's object-tracking structures across the userspace security boundary, yielding kernel memory corruption (potential privilege escalation) or a kernel crash (denial of service). The fix removes objfreelock and serializes every objlist modification under listslock, including holding it across find+remove in kobjectfree() and around unrefcheck() in kthreadpermsclear(). Affects CONFIGSMP+CONFIGUSERSPACE+CONFIGDYNAMICOBJECTS configurations; the defect dates to the 2019 spinlockification (commit 8a3d57b6cc6, first released in v1.14.0) and shipped through v4.4.0.

First published (updated )
Severity
4.6
Use After Free
AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

The Nuvoton NuMaker HSUSBD USB device-controller driver (drivers/usb/udc/udcnumaker.c) armed the control Data IN stage unconditionally (base->CEPTXCNT = len in numakerhsusbdeptrigger). Because the HSUSBD hardware cannot disarm a control Data IN already armed for a previous transfer, a USB host that cancels an in-flight control transfer (timeout) and then issues a new SETUP packet can drive the driver out of sync: stale data may be transmitted in the new transfer and the control endpoint can become permanently stuck NAK'ing every subsequent control transfer.

A malicious or buggy host (physical/adjacent attacker driving the bus) can repeatedly cancel-and-re-SETUP to wedge the device's USB control endpoint, denying service to the device's USB function (the device stops enumerating/responding on the control pipe) until a USB reset or re-plug. The flaw is an availability-only denial of service; the FIFO copy loops (bounded by netbuf length and the hardware BUFFULL flag) and the netbuf lifecycle are independent of the arming desync, so there is no out-of-bounds access, use-after-free, or information leak.

The fix monitors the IN-token and new-SETUP events (kevent) and only arms control Data IN when an IN token is present and no new SETUP has arrived, cancelling the current transfer on a new SETUP. Affects boards using the Nuvoton NuMaker HSUSBD controller (CONFIGUDCNUMAKER with DTHASNUVOTONNUMAKERHSUSBDENABLED); shipped in v4.4.0.

First published (updated )
Severity
8.2
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H

The hawkBit device management client in subsys/mgmt/hawkbit accumulates the body of an HTTP response from the update server into a heap buffer in responsejsoncb() (subsys/mgmt/hawkbit/hawkbit.c). The buffer is sized to hold the received body bytes but reserves no space for a terminating NUL. When the full response has arrived, the code writes responsedata[downloadedsize] = '\0' — and whenever the accumulated body length equals the allocation, that terminator lands one byte past the end of the heap object (a heap-based out-of-bounds write, CWE-122 / CWE-787).

The body length and fragmentation are taken directly from the parsed HTTP response (rsp->bodyfragstart / rsp->bodyfraglen) and are fully controlled by the remote hawkBit server, which chooses its own response length. The precise trigger depends on how the buffer grows, and both forms are remotely reachable. Since v4.0.0 the reallocation is sized to exactly downloadedsize + bodylen, so any response body larger than the 1100-byte initial buffer makes the out-of-bounds write deterministic; such response sizes are normal for hawkBit deployment metadata. Before v4.0.0 the buffer grew by doubling and the growth check ((downloadedsize + bodylen) > responsebuffersize) is false at equality, so a response body whose length is exactly the current allocation — 1100 bytes with the default initial buffer — skips the reallocation entirely and writes the terminator at responsedata[1100] of an 1100-byte object. The HTTP length-mismatch check does not catch this, because the declared and received lengths genuinely agree. Either form is reachable by a malicious, compromised, or man-in-the-middle update server (TLS is optional and, when enabled, does not protect against a hostile server), with no authentication of response content and no client-side length cap protecting the write.

The out-of-bounds write is a fixed single NUL byte immediately following the allocation, corrupting adjacent allocator metadata or the next allocation. The practical impact is heap corruption leading to denial of service (fault on a subsequent allocation or free), with the bounded, allocator-dependent possibility of further corruption. The fix sizes the buffer to the body length plus one and copies with memcpy, ensuring the terminator always lands within the allocation.

First published (updated )
Severity
6.1
Use After Free
AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

In Zephyr's experimental USB host stack (CONFIGUSBHOSTSTACK), usbhdevicedisconnect() (subsys/usb/host/usbhdevice.c) freed the root usbdevice slab object without clearing the cached pointer ctx->root. The bus removal handler devremovedhandler() (subsys/usb/host/usbhcore.c) decides what to tear down solely from ctx->root, checking only that it is non-NULL.

Because UHC controller drivers (e.g. uhcmax3421e, uhcmcuxcommon) synthesize UHCEVTDEVREMOVED directly from physical bus line state with no debounce or state guard, an attacker with physical USB access (or a rogue device that bounces its connection) can deliver a second device-removed event after a root device disconnect. The handler then re-enters usbhdevicedisconnect() with the dangling pointer, locking a mutex inside the freed object (use-after-free), removing the freed node from the device list, and calling kmemslabfree() on the already-freed block (double-free). If the slab block has been reissued to a newly attached device in between, this corrupts a live object.

Impact is denial of service (crash) and memory corruption; the attack vector is physical/local. The flaw was introduced in v4.4.0 by the connect/disconnect refactor and is fixed by clearing ctx->root in usbhdevicedisconnect() before freeing.

First published (updated )
Severity
5.5
Null Pointer Dereference
AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

The CONFIGUSERSPACE verification handler for the kthreadnamecopy() system call (zvrfykthreadnamecopy() in kernel/thread.c) calls kobjectfind() on the caller-supplied thread pointer and then dereferences the returned struct kobject without checking it for NULL. kobjectfind() returns NULL whenever the supplied pointer is not a registered (static or dynamic) kernel object.

The pre-fix guard tested thread == NULL instead of ko == NULL, so an unprivileged user-mode thread that invokes kthreadnamecopy() with any non-NULL but unregistered pointer (e.g. an arbitrary address) passes the NULL test, after which the verifier reads ko->type through a NULL pointer.

Because the syscall verifier runs in supervisor mode, this NULL dereference is a kernel-mode fault that halts or reboots the system, allowing untrusted user code to crash the kernel across the userspace security boundary (denial of service). The marshaller passes the thread argument to the verifier without any prior KSYSCALLOBJ validation, so the bad pointer reaches the defect directly.

The flaw affects builds with CONFIGUSERSPACE and CONFIGTHREADNAME enabled and has been present since the special-case lookup was introduced around v2.0.0; it is present in v4.4.0 and earlier. The fix changes the guard to check the kobjectfind() return value (ko == NULL) before dereferencing it.

First published (updated )
Severity
7.1
AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H

Zephyr's Bluetooth Classic Hands-Free Profile (HFP) Hands-Free role parser (subsys/bluetooth/host/classic/hfphf.c) contains an out-of-bounds write. During Service Level Connection setup the HF sends AT+CIND=? and parses the AG's +CIND: response in cindhandle(), which assigns a per-entry counter index and calls cindhandlevalues() for each list element. cindhandlevalues() then wrote hf->indtable[index] = i without verifying that index is within the 20-element int8t indtable[] array of struct bthfphf. Because the parser places no cap on the number of +CIND: list entries, a remote Attendant Gateway (a malicious, compromised, or spoofed peer the device connects to over Bluetooth) can send a response with more than 20 recognized indicator entries and drive index arbitrarily large, writing a small attacker-positioned value past the array into adjacent struct fields (feature masks, SDP/version state, the calls[] array, work/atomic bookkeeping) and potentially beyond the static connection pool slot. This yields memory corruption and at least denial of service of the Bluetooth host, triggered by a single malformed AT response with no user interaction. The sibling consumer agindicatorhandlevalues() already performed the equivalent bounds check; this commit adds the same index >= ARRAYSIZE(hf->indtable) guard to close the gap. Affects builds with CONFIGBTHFPHF enabled; introduced with the original HFP HF CIND parser (~v1.7) and present through v4.4.0.

First published (updated )
Severity
7.8
AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:H

The userspace verifier zvrfylogfilterset() for the logfilterset syscall in subsys/logging/logmgmt.c performed a signed comparison against the int16t srcid parameter: srcid < (int16t)logsrccntget(domainid). Any negative value for srcid (e.g. -1) trivially satisfied this check and was forwarded into zimpllogfilterset, where it propagated to filterset() and ultimately to getdynamicfilter(), which uses sourceid as an unsigned index into the linker-section array &TYPESECTIONSTART(logdynamic)[sourceid].filters.

After implicit conversion through uint32t, an int16t -1 becomes 0xFFFFFFFF, indexing logdynamic far out of bounds and causing the kernel to perform an OOB read and an OOB read-modify-write (LOGFILTERSLOTGET/SET) against memory adjacent to the logdynamic section.

The written value is a constrained 3-bit log level slot within the targeted 32-bit word, but the target address is attacker-chosen (a small negative offset from logdynamic) and the write occurs in supervisor mode following a syscall from an unprivileged user thread, providing a kernel memory-corruption / privilege-escalation primitive.

The defect is reachable on any build with CONFIGUSERSPACE=y and CONFIGLOGRUNTIMEFILTERING=y. Present from Zephyr v3.3.0 through v4.4.1. The fix replaces the signed bound check with an unsigned comparison: (uint32t)srcid < logsrccntget(domainid), which correctly rejects negative inputs.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:L

Zephyr's IPv6 forwarding path re-sent routed unicast packets without ever decrementing the IPv6 hop limit. Both routing branches of ipv6routepacket() (subsys/net/ip) were affected: the explicit-route path (netroutepacket()) and the on-link cross-interface path (netroutepacketif()). Each set the packet forwarding flag and called netsenddata() with the hop limit untouched and no expiry check.

Per RFC 8200 the hop-limit decrement is the mechanism that bounds packet lifetime and terminates routing loops; without it, a device acting as an IPv6 router relays looping packets indefinitely. An on-path attacker who can induce or exploit a transient L3 loop turns it into a permanent forwarding storm, causing CPU/bandwidth resource exhaustion (availability DoS) on the forwarder and adjacent links; path-discovery and loop diagnostics that rely on hop-limit expiry are also defeated.

Affected configurations. In every affected release the forwarding path is reached via CONFIGNETROUTE (enabled by default when CONFIGNETIPV6NBRCACHE is set), together with CONFIGNETROUTING for cross-interface routing. Note that CONFIGNETIPV6FORWARDING and CONFIGNETIPV4FORWARDING — which appear in the fix and in this advisory's evidence notes — were introduced after v4.4.0, when the routing options were split and renamed; they do not exist in any affected release. When auditing a v4.4.1-or-earlier configuration, look for CONFIGNETROUTE and CONFIGNETROUTING.

IPv4 is not affected in any release. The IPv4 forwarding path (netrouteipv4packet() in routeipv4.c) was added after v4.4.0 and has never shipped in a release. Its TTL decrement and IPv4 header-checksum recomputation landed on main as part of the same fix, so the evidence notes below discuss it, but no released version is reachable by way of IPv4.

Affected releases are v1.8.0 through v4.4.1: v1.8.0 introduced netroutepacket() and v2.2.0 added netroutepacketif(), and neither decremented the hop limit. v4.3.1 carries the explicit-route fix but not the on-link one, so it is affected as well. Fixed on main by 7d8f1afa7345 (explicit-route path) and 589eadc74efa (on-link path).

First published (updated )
Severity
7.1
Use After Free
AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:H

subsys/net/ip/ipv6mld.c:mldsend() read the packet interface via netpktiface(pkt) after netsenddata(pkt) returned successfully. Per the network stack's ownership contract (include/zephyr/net/netcore.h, and the explicit warning in subsys/net/ip/netcore.c:453-460 'do not use pkt after that call'), a successful send transfers ownership of the netpkt and the L2 driver frees it (e.g. ethernetsend() unrefs the packet on success, subsys/net/l2/ethernet/ethernet.c:790), returning it to its kmemslab.

The subsequent netpktiface(pkt) is therefore a read of a freed object; the recovered interface pointer is then dereferenced and incremented by the per-interface statistics path (netstats.h UPDATESTAT/SETSTAT) when CONFIGNETSTATISTICSPERINTERFACE is enabled. If the freed slot is concurrently reallocated, pkt->iface may read back as NULL (NULL-pointer dereference / crash) or as a stale/garbage pointer (stray increment write / memory corruption).

The path is reachable remotely on the local link without authentication: handlemldquery() (registered for NETICMPV6MLDQUERY) responds to a valid MLDv2 General Query (unspecified multicast address, hop limit 1) by calling sendmldreport() -> mldsend().

The result is a remotely triggerable denial of service of the networking stack, with a narrow possibility of memory corruption. The fix caches the interface in a local before sending and no longer touches the packet after netsenddata(). The IPv4/IGMP sibling (igmpsend) already used the corrected pattern.

First published (updated )
Severity
7.1
Input Validation
AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

btsdpparseattribute() in subsys/bluetooth/host/classic/sdp.c validated only that the SDP record buffer held the type-marker byte plus the 2-byte attribute ID (a check of buf->len < 3) but then read a fourth byte, the data-element descriptor (type), via netbufsimplepullu8(). Because netbufsimplepullu8() dereferences buf->data[0] before its only bounds guard (an ASSERTNOMSG that compiles out when CONFIGASSERT is disabled, the production default), a record of exactly three bytes (0x09 followed by a 2-byte attribute ID) causes a one-byte read past the end of the logical buffer. The parser is reachable from inbound, remote-controlled data: a Bluetooth BR/EDR peer acting as an SDP server returns discovery-response records that are stored verbatim in the client receive buffer and parsed via the public btsdpgetattr()/btsdphasattr()/btsdprecordparse() helpers. The over-read is bounded to a single byte that is used only as an internal length selector and is never leaked to the attacker; subsequent length checks then reject the malformed record. Realistic impact is therefore limited to an edge-case denial of service (a fault only if the record ends exactly at a mapped-memory boundary, or a deterministic assert panic when CONFIGASSERT=y). Affects Zephyr v4.3.0 and v4.4.0; fixed by adding sizeof(type) to the length check.

First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203