The Bluetooth Mesh On-Demand Private Proxy solicitation handler in subsys/bluetooth/mesh/solicitation.c copies a received Solicitation PDU into a fixed 17-byte stack buffer without bounding the source length. In solpdudecrypt(), out is allocated as NETBUFSIMPLE(17) and then filled with netbufsimpleaddmem(out, in->data, in->len); netbufsimpleadd() guards its tailroom only with ASSERTNOMSG, which is compiled out in production builds, so when in->len > 17 the underlying memcpy writes attacker-controlled bytes past the 17-byte stack buffer. The copy occurs before any decryption or authentication, so no key material is required to trigger it.
The oversized length arises because the mesh scan callback in subsys/bluetooth/mesh/adv.c calls netbufsimplerestore() before dispatching to btmeshsolrecv(), leaving buf->len covering the entire remaining advertising payload rather than just the Solicitation Service Data. After the parser locates the Service Data AD and consumes the Identification Type byte, the remaining buf->len is the 17-octet Network PDU plus any trailing advertising bytes, and prior to this fix there was no maximum-length check (only a minimum). An attacker can therefore append extra AD structures or padding after the Solicitation Service Data to make buf->len exceed 17.
btmeshscancb() is registered directly as the BLE scan callback, so buf is raw, unauthenticated advertising data received over the air. Any device in radio range can send a non-connectable advertisement carrying a crafted mesh Proxy Solicitation to a node that has CONFIGBTMESHODPRIVPROXYSRV enabled and is currently eligible to be solicited (GATT proxy disabled, On-Demand Private Proxy enabled), with no pairing, bonding, or provisioning. The result is an attacker-controlled stack overwrite — plausibly leading to remote code execution and at minimum a reliable remote denial of service. The fix trims buf->len to the spec-fixed 17 octets (dropping the PDU if fewer remain) before decryption.
ieee802154send() in subsys/net/l2/ieee802154/ieee802154.c copies the outgoing packet into a single fixed 125-byte transmit buffer (txframebufpool, sized IEEE802154MTU). In builds with CONFIGNETL2IEEE802154FRAGMENT enabled (the default whenever CONFIGNET6LO is set), the branch taken when 6LoWPAN fragmentation is not required performed an unchecked netbufaddmem(framebuf, pktbuf->data, pktbuf->len). The only guard was ASSERTNOMSG() inside netbufsimpleadd(), which is compiled out without CONFIGASSERT, so an oversized packet silently overran the frame buffer.
The defect is not reachable from the radio: for NETAFINET6 packets ieee8021546loencodepkt() compares the whole packet length against IEEE802154MTU and takes the fragmentation path when it does not fit, so every buffer copied on the unfragmented branch is within bounds. It is reachable through NETAFPACKET sockets bound to an 802.15.4 interface: for NETSOCKRAW the 6LoWPAN block is skipped entirely and for NETSOCKDGRAM it returns early on the address-family test, leaving no length validation anywhere on the transmit path (netcontextsendto() and netiftx() apply none, and pktbufferlength() does not clamp the allocation for this L2).
An application — or, in a CONFIGUSERSPACE build, an unprivileged application thread using the zsocksocket()/zsocksendto() syscalls — can therefore drive a supervisor-mode out-of-bounds write of chosen bytes past the 125-byte pool buffer. With the default CONFIGNETBUFFIXEDDATASIZE of 128 bytes the overrun is bounded to roughly llhdrlen + 3 bytes; with CONFIGNETBUFVARIABLEDATASIZE a single storage buffer can be as large as CONFIGNETPKTBUFTXDATAPOOLSIZE, making the overrun far larger. The consequence is corruption of memory adjacent to the pool, with a crash or further compromise of kernel state as the practical impact.
The fix validates llhdrlen + netpktgetlen(pkt) + authtaglen against IEEE802154MTU before any copy and adds a tailroom-checking copypkttoframe() helper that returns -EMSGSIZE instead of overrunning the buffer. The same change also linearizes the whole netbuf chain into one MAC frame, so packet storage boundaries no longer become frame boundaries on the wire.