* [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses
@ 2026-09-24 6:22 Hui Peng
2026-09-24 6:22 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Hui Peng @ 2026-09-24 6:22 UTC (permalink / raw)
To: h.morris, alex.aring, miquel.raynal, stefan
Cc: david.laight.linux, linux-wpan, netdev, linux-kernel, stable,
Hui Peng
This series fixes three out-of-bounds access bugs in the Cascoda CA8210
IEEE 802.15.4 driver:
1. Reject received SPI packets with len > sizeof(struct mac_message) in
ca8210_rx_done() instead of checking len > CA8210_SPI_BUF_SIZE (256),
preventing a stack buffer overflow when copying a synchronous response
into priv->sync_command_response (a struct mac_message on the caller's
stack) and matching the actual SPI transfer length
(cas_ctl->transfer.len = sizeof(struct mac_message)).
2. Initialize lenvar = 1 in ca8210_get_ed() and validate
hw_attribute_length against *hw_attribute_length in
hwme_get_request_sync() before memcpy() to prevent overflowing the
caller's stack buffer.
3. Validate the received SPI frame length len upfront at the start of
ca8210_skb_rx() before reading data_ind or allocating the skb.
Changes in v3:
- Patch 1/3: Check len > sizeof(struct mac_message) in ca8210_rx_done()
where dev_crit() logs "Received packet len (%u) erroneously long" and
drops the packet, instead of silently truncating the memcpy() with
min_t(), addressing David Laight's feedback.
Changes in v2:
- Split the ca8210 fixes into three single-issue patches (1/3..3/3) and
addressed Miquel Raynal's review comments on patches 2/3 and 3/3.
Hui Peng (3):
ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done()
ieee802154: ca8210: prevent stack buffer overflow in
hwme_get_request_sync()
ieee802154: ca8210: validate data_ind length upfront in
ca8210_skb_rx()
drivers/net/ieee802154/ca8210.c | 39 +++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 12 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() 2026-09-24 6:22 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng @ 2026-09-24 6:22 ` Hui Peng 2026-09-24 6:22 ` [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() Hui Peng 2026-09-24 6:22 ` [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() Hui Peng 2 siblings, 0 replies; 10+ messages in thread From: Hui Peng @ 2026-09-24 6:22 UTC (permalink / raw) To: h.morris, alex.aring, miquel.raynal, stefan Cc: david.laight.linux, linux-wpan, netdev, linux-kernel, stable, Hui Peng In ca8210_spi_transfer(), each SPI transfer reads sizeof(struct mac_message) bytes into cas_ctl->tx_in_buf: cas_ctl->transfer.len = sizeof(struct mac_message); However, ca8210_rx_done() only checks the received packet length len = buf[1] + 2 against CA8210_SPI_BUF_SIZE (256). When buf[0] & SPI_SYN is set and priv->sync_command_response is non-NULL, memcpy() copies up to 256 bytes into priv->sync_command_response, which points to a struct mac_message object on the synchronous caller's stack, overflowing the stack buffer: BUG: KASAN: stack-out-of-bounds in ca8210_rx_done+0x117/0x6c0 Write of size 256 at addr ffff8881009e7c40 by task swapper/0/1 Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x125/0x200 __asan_memcpy+0x3c/0x60 ca8210_rx_done+0x117/0x6c0 ... This frame has 1 object: [32, 182) 'response' Check len > sizeof(struct mac_message) instead of len > CA8210_SPI_BUF_SIZE in ca8210_rx_done() so that any packet exceeding sizeof(struct mac_message) is logged as erroneously long via dev_crit() and dropped before copying into priv->sync_command_response or passing it to ca8210_net_rx(). Tested in QEMU with KASAN enabled by passing a 256-byte SPI_SYN response into ca8210_rx_done(). Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v3: - Check len > sizeof(struct mac_message) at the top of ca8210_rx_done() where dev_crit() logs the error and drops the packet instead of silently truncating memcpy() with min_t(), addressing David Laight's feedback. Changes in v2: - Split the ca8210 fixes into three single-issue patches (1/3..3/3). drivers/net/ieee802154/ca8210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 01af4f9..a990a0f 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -686,7 +686,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl) buf = cas_ctl->tx_in_buf; len = buf[1] + 2; - if (len > CA8210_SPI_BUF_SIZE) { + if (len > sizeof(struct mac_message)) { dev_crit( &priv->spi->dev, "Received packet len (%u) erroneously long\n", -- 2.49.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() 2026-09-24 6:22 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng 2026-09-24 6:22 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng @ 2026-09-24 6:22 ` Hui Peng 2026-09-28 6:42 ` netdev-bot+sashiko 2026-09-24 6:22 ` [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() Hui Peng 2 siblings, 1 reply; 10+ messages in thread From: Hui Peng @ 2026-09-24 6:22 UTC (permalink / raw) To: h.morris, alex.aring, miquel.raynal, stefan Cc: david.laight.linux, linux-wpan, netdev, linux-kernel, stable, Hui Peng In ca8210_get_ed(), an uninitialized u8 lenvar and a pointer to a 1-byte stack buffer (u8 *level) are passed to hwme_get_request_sync(), which unconditionally copies response.pdata.hwme_get_cnf.hw_attribute_length bytes into hw_attribute_value without checking the caller's destination buffer capacity, overflowing level on the stack when hw_attribute_length exceeds 1: BUG: KASAN: stack-out-of-bounds in hwme_get_request_sync.constprop.0.isra.0+0xf3/0x170 Write of size 16 at addr ffff888001907780 by task init/1 Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x125/0x200 __asan_memcpy+0x3c/0x60 hwme_get_request_sync.constprop.0.isra.0+0xf3/0x170 ca8210_get_ed+0x9c/0xf0 ... The buggy address belongs to stack of task init/1 and is located at offset 48 in frame: ca8210_get_ed+0x0/0xf0 This frame has 2 objects: [48, 49) 'level' [64, 65) 'lenvar' Initialize lenvar = 1 in ca8210_get_ed() and return IEEE802154_SYSTEM_ERROR in hwme_get_request_sync() if response.pdata.hwme_get_cnf.hw_attribute_length exceeds *hw_attribute_length. Tested in QEMU with KASAN enabled by passing an oversized hw_attribute_length response into ca8210_get_ed(). Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v3: - No changes. Changes in v2: - Split out as patch 2/3. - Replaced the temporary stack buffer in ca8210_get_ed() with lenvar = 1 and an upper-bound check against *hw_attribute_length in hwme_get_request_sync() as requested by Miquel Raynal. drivers/net/ieee802154/ca8210.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index a990a0f..8aa7ffe 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -1677,6 +1677,9 @@ static u8 hwme_get_request_sync( return IEEE802154_SYSTEM_ERROR; if (response.pdata.hwme_get_cnf.status == IEEE802154_SUCCESS) { + if (response.pdata.hwme_get_cnf.hw_attribute_length > + *hw_attribute_length) + return IEEE802154_SYSTEM_ERROR; *hw_attribute_length = response.pdata.hwme_get_cnf.hw_attribute_length; memcpy( @@ -2027,7 +2030,7 @@ static int ca8210_xmit_async(struct ieee802154_hw *hw, struct sk_buff *skb) */ static int ca8210_get_ed(struct ieee802154_hw *hw, u8 *level) { - u8 lenvar; + u8 lenvar = 1; struct ca8210_priv *priv = hw->priv; return link_to_linux_err( ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() 2026-09-24 6:22 ` [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() Hui Peng @ 2026-09-28 6:42 ` netdev-bot+sashiko 0 siblings, 0 replies; 10+ messages in thread From: netdev-bot+sashiko @ 2026-09-28 6:42 UTC (permalink / raw) To: benquike Cc: h.morris, alex.aring, miquel.raynal, stefan, david.laight.linux, linux-wpan, netdev, linux-kernel, stable, kuba Thank you for your contribution! Sashiko AI review found more severe issue(s) in other patches of this series. This mail is only an FYI, in case you want to address the nit picks below when you respin. Low priority / nit picks for your consideration: - [Low] The commit message reads as if the stack overflow in ca8210_get_ed()/hwme_get_request_sync() can happen at runtime. - [Low] The patch turns `hw_attribute_length` in hwme_get_request_sync() into an in/out parameter, but the kernel-doc was not updated. Pre-existing issues: - [High] This problem wasn't introduced by this patch, but it is a real memory-safety race in the same sync-exchange path. -- ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() This patch initializes lenvar to 1 in ca8210_get_ed(). It also makes hwme_get_request_sync() return IEEE802154_SYSTEM_ERROR when the device reports an hw_attribute_length larger than the caller's buffer. The goal is to stop a stack overflow of the 1-byte level buffer in ca8210_get_ed(). > In ca8210_get_ed(), an uninitialized u8 lenvar and a pointer to a 1-byte > stack buffer (u8 *level) are passed to hwme_get_request_sync(), which > unconditionally copies response.pdata.hwme_get_cnf.hw_attribute_length > bytes into hw_attribute_value without checking the caller's destination > buffer capacity, overflowing level on the stack when hw_attribute_length > exceeds 1: > > BUG: KASAN: stack-out-of-bounds in hwme_get_request_sync.constprop.0.isra.0+0xf3/0x170 > Write of size 16 at addr ffff888001907780 by task init/1 [ ... ] > Tested in QEMU with KASAN enabled by passing an oversized > hw_attribute_length response into ca8210_get_ed(). > > Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") > Cc: stable@vger.kernel.org [Severity: Low] Can this overflow actually be reached at runtime? The commit message reads as if it describes live stack corruption. It shows a splat from task init/1 and carries a stable tag. hwme_get_request_sync() is static. Its only caller is ca8210_get_ed(), and ca8210_get_ed() is only referenced as the .ed callback in ca8210_phy_ops: .ed = ca8210_get_ed, As far as I can tell, mac802154 never calls ops->ed. The only reference is the NULL check in ieee802154_alloc_hw(): net/mac802154/main.c:ieee802154_alloc_hw() { ... if (WARN_ON(!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed || ... } nl802154_trigger_scan() also accepts only NL802154_SCAN_ACTIVE and NL802154_SCAN_PASSIVE. So an energy-detection scan from userspace can't get there either. Even if there were a caller, the device would have to answer HWME_GET(HWME_EDVALUE) with hw_attribute_length > 1. Could the commit message say that the .ed op is not currently invoked, and that a misbehaving CA8210 would be needed? That would help maintainers choose between net and net-next, and decide whether a stable backport is needed. > diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c > index a990a0f347ad..8aa7ffeb22d7 100644 > --- a/drivers/net/ieee802154/ca8210.c > +++ b/drivers/net/ieee802154/ca8210.c > @@ -1677,6 +1677,9 @@ static u8 hwme_get_request_sync( > return IEEE802154_SYSTEM_ERROR; > > if (response.pdata.hwme_get_cnf.status == IEEE802154_SUCCESS) { > + if (response.pdata.hwme_get_cnf.hw_attribute_length > > + *hw_attribute_length) > + return IEEE802154_SYSTEM_ERROR; [Severity: Low] Should the kernel-doc for hwme_get_request_sync() be updated too? *hw_attribute_length is now read as the size of hw_attribute_value, and then overwritten with the copied length. That makes it an in/out parameter. The comment still says: * @hw_attribute_length: Attribute length ... * Return: 802.15.4 status code of HWME-GET.confirm Before this patch the argument was only written, which is why ca8210_get_ed() could pass an uninitialized lenvar. A future caller that follows the kernel-doc and does the same would compare against a random value, and the overflow would come back. The only caller meets the new requirement with a bare "u8 lenvar = 1;". Nothing ties that 1 to sizeof(*level). The Return: text is now also wrong in one more case. This IEEE802154_SYSTEM_ERROR comes from the driver, not from the device's confirm, and link_to_linux_err() maps it to -EPROTO. Two older SYSTEM_ERROR returns had already made that text inaccurate. > *hw_attribute_length = > response.pdata.hwme_get_cnf.hw_attribute_length; > memcpy( [Severity: High] This isn't a bug introduced by this patch, but there seems to be a race in the sync exchange path that this length check can't protect against. priv->sync_command_response is per-device state shared by all sync callers, and no lock covers it. ca8210_spi_exchange() publishes the caller's stack buffer, waits interruptibly with a timeout, and then clears the pointer: drivers/net/ieee802154/ca8210.c:ca8210_spi_exchange() { ... if ((buf[0] & SPI_SYN) && response) { /* if sync wait for confirm */ reinit_completion(&priv->sync_exchange_complete); priv->sync_command_response = response; } ... cleanup: priv->sync_command_response = NULL; return status; } ca8210_rx_done() runs from the SPI completion callback ca8210_spi_transfer_complete(). It tests the pointer and then copies into it, with no lock: drivers/net/ieee802154/ca8210.c:ca8210_rx_done() { ... if (buf[0] & SPI_SYN) { if (priv->sync_command_response) { memcpy(priv->sync_command_response, buf, len); complete(&priv->sync_exchange_complete); ... } Suppose the waiter gets -ERESTARTSYS or -ETIME after ca8210_rx_done() has loaded the non-NULL pointer but before the memcpy. Can that memcpy then write into the stack frame of a caller that has already returned from hwme_get_request_sync()? Sync exchanges also don't appear to be serialized. ca8210_mlme_reset_worker() calls mlme_reset_request_sync() from a workqueue without rtnl, and ca8210_rx_done() queues it on TRANSACTION_OVERFLOW. It can run at the same time as rtnl-held ieee802154_ops callbacks such as set_channel or set_txpower, which also use the *_request_sync() helpers. Could two callers overwrite each other's response pointer, or consume each other's completion? One caller would get the other command's confirm. The other would either time out or return with its response buffer untouched, because hwme_get_request_sync() doesn't preset command_id. Would it make sense to serialize sync exchanges with a mutex? The handoff of the response buffer would also need to be synchronized against ca8210_rx_done(). Ideally, the confirm ID would also be checked against the request that was issued. [ ... ] -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260924062244.2444225-1-benquike%40gmail.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() 2026-09-24 6:22 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng 2026-09-24 6:22 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng 2026-09-24 6:22 ` [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() Hui Peng @ 2026-09-24 6:22 ` Hui Peng 2026-09-28 6:42 ` netdev-bot+sashiko 2 siblings, 1 reply; 10+ messages in thread From: Hui Peng @ 2026-09-24 6:22 UTC (permalink / raw) To: h.morris, alex.aring, miquel.raynal, stefan Cc: david.laight.linux, linux-wpan, netdev, linux-kernel, stable, Hui Peng In ca8210_skb_rx(), data_ind is read at offsets 22 (msdulen), 23 (mpdulinkquality), 29 + msdulen (hdr.sec.level), 30..39 + msdulen (security header), and 29 .. 29 + msdulen (payload) without verifying that the received SPI frame length len covers those offsets, causing an out-of-bounds read when msdulen exceeds len - 30: BUG: KASAN: slab-out-of-bounds in ca8210_skb_rx.constprop.0.isra.0+0x137/0x160 Read of size 64 at addr ffff888006453ddd by task init/1 Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x125/0x200 __asan_memcpy+0x23/0x60 ca8210_skb_rx.constprop.0.isra.0+0x137/0x160 ca8210_net_rx+0x96/0xc0 ... The buggy address belongs to the object at ffff888006453dc0 which belongs to the cache kmalloc-32 of size 32 The buggy address is located 29 bytes inside of allocated 32-byte region [ffff888006453dc0, ffff888006453de0) Consolidate all length and msdulen validations into a single upfront check at the beginning of ca8210_skb_rx() before allocating the skb. Tested in QEMU with KASAN enabled by passing a short data_ind buffer with msdulen = 64 and len = 30 into ca8210_skb_rx(). Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v3: - No changes. Changes in v2: - Split out as patch 3/3. - Consolidated all length checks in ca8210_skb_rx() into a single place at the beginning of the function before dev_alloc_skb() and dropped the unrelated hdr.seq assignment as requested by Miquel Raynal. drivers/net/ieee802154/ca8210.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 8aa7ffe..ab245ad 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -1758,19 +1758,15 @@ static int ca8210_skb_rx( u8 *data_ind ) { - struct ieee802154_hdr hdr; + struct ieee802154_hdr hdr = { }; int msdulen; int hlen; - u8 mpdulinkquality = data_ind[23]; + u8 mpdulinkquality; struct sk_buff *skb; struct ca8210_priv *priv = hw->priv; - /* Allocate mtu size buffer for every rx packet */ - skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr)); - if (!skb) - return -ENOMEM; - - skb_reserve(skb, sizeof(hdr)); + if (len < 30) + return -EMSGSIZE; msdulen = data_ind[22]; /* msdu_length */ if (msdulen > IEEE802154_MTU) { @@ -1778,9 +1774,25 @@ static int ca8210_skb_rx( &priv->spi->dev, "received erroneously large msdu length!\n" ); - kfree_skb(skb); return -EMSGSIZE; } + + if (len < 30 + msdulen || + (!priv->promiscuous && data_ind[29 + msdulen] > 0 && + len < 29 + msdulen + sizeof(struct secspec))) { + dev_err(&priv->spi->dev, + "received truncated data indication!\n"); + return -EMSGSIZE; + } + + mpdulinkquality = data_ind[23]; + + /* Allocate mtu size buffer for every rx packet */ + skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr)); + if (!skb) + return -ENOMEM; + + skb_reserve(skb, sizeof(hdr)); dev_dbg(&priv->spi->dev, "skb buffer length = %d\n", msdulen); if (priv->promiscuous) ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() 2026-09-24 6:22 ` [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() Hui Peng @ 2026-09-28 6:42 ` netdev-bot+sashiko 0 siblings, 0 replies; 10+ messages in thread From: netdev-bot+sashiko @ 2026-09-28 6:42 UTC (permalink / raw) To: benquike Cc: h.morris, alex.aring, miquel.raynal, stefan, david.laight.linux, linux-wpan, netdev, linux-kernel, stable, kuba Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider. Critical: 0 · High: 1 · Medium: 2 · Low: 1 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] ieee802154: ca8210: TOCTOU race on priv->promiscuous allows OOB read - [Medium] The commit message overstates the impact. - [Medium] The new upfront length check in ca8210_skb_rx() does not cover the first read of the MCPS-DATA.indication fields. - [Low] The patch changes `struct ieee802154_hdr hdr;` to `struct ieee802154_hdr hdr = { };` in ca8210_skb_rx()… -- ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() This patch moves the length checks in ca8210_skb_rx() to the start of the function, ahead of the skb allocation. It adds a minimum length check, a check that len covers the msdu, and a check that len covers the security header. It also zero-initialises the on-stack struct ieee802154_hdr. > In ca8210_skb_rx(), data_ind is read at offsets 22 (msdulen), 23 > (mpdulinkquality), 29 + msdulen (hdr.sec.level), 30..39 + msdulen > (security header), and 29 .. 29 + msdulen (payload) without verifying > that the received SPI frame length len covers those offsets, causing an > out-of-bounds read when msdulen exceeds len - 30: > > BUG: KASAN: slab-out-of-bounds in ca8210_skb_rx.constprop.0.isra.0+0x137/0x160 > Read of size 64 at addr ffff888006453ddd by task init/1 [ ... ] > The buggy address belongs to the object at ffff888006453dc0 > which belongs to the cache kmalloc-32 of size 32 [Severity: Medium] Can the real driver produce this slab-out-of-bounds read? The only caller of ca8210_skb_rx() is ca8210_net_rx(), which gets its buffer from ca8210_rx_done(): drivers/net/ieee802154/ca8210.c:ca8210_rx_done() { ... buf = cas_ctl->tx_in_buf; len = buf[1] + 2; ... ca8210_net_rx(priv->hw, buf, len); ... } ca8210_net_rx() then does: return ca8210_skb_rx(hw, len - 2, command + 2); tx_in_buf is a fixed u8 tx_in_buf[CA8210_SPI_BUF_SIZE] (256 bytes) that sits inside struct cas_control. It is memset to SPI_IDLE before each transfer. msdulen is already capped at IEEE802154_MTU (127). So the highest byte ca8210_skb_rx() can touch is tx_in_buf[2 + 39 + 127], which is inside the object. The kmalloc-32 splat seems to come from the test harness passing a 32-byte buffer directly into ca8210_skb_rx(). The underlying problem looks like missing validation of a truncated MCPS-DATA.indication, not a read outside the allocation. With Cc: stable attached, could the commit message describe the real impact more precisely, so stable and CVE triage are not misled? > diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c > index 8aa7ffeb22d7..ab245add9ff5 100644 > --- a/drivers/net/ieee802154/ca8210.c > +++ b/drivers/net/ieee802154/ca8210.c > @@ -1758,19 +1758,15 @@ static int ca8210_skb_rx( > u8 *data_ind > ) > { > - struct ieee802154_hdr hdr; > + struct ieee802154_hdr hdr = { }; [Severity: Low] This isn't a bug, but this change in behaviour isn't mentioned in the commit message. ieee802154_hdr_push() writes hdr->seq and the full 2-byte frame control into the skb: net/ieee802154/header_ops.c:ieee802154_hdr_push() { ... buf[pos++] = hdr->seq; ... memcpy(buf, fc, 2); memcpy(skb_push(skb, pos), buf, pos); ... } ca8210_skb_rx() never sets hdr.seq, fc.ack_request, fc.frame_pending, the reserved fc bits or sec.frame_counter. Before this patch, uninitialised stack bytes ended up in the reconstructed MAC header of every non-promiscuous received frame. After this patch those fields are always zero, so seq is 0 for every frame. The v2 changelog says the hdr.seq assignment was dropped as unrelated. Could this initialisation either get its own patch or be described in this commit message? Otherwise a backporter might drop it as unrelated and bring the stack data leak back. > int msdulen; > int hlen; > - u8 mpdulinkquality = data_ind[23]; > + u8 mpdulinkquality; > struct sk_buff *skb; > struct ca8210_priv *priv = hw->priv; > > - /* Allocate mtu size buffer for every rx packet */ > - skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr)); > - if (!skb) > - return -ENOMEM; > - > - skb_reserve(skb, sizeof(hdr)); > + if (len < 30) > + return -EMSGSIZE; [Severity: Medium] This check runs only after the caller has already read and stored a data_ind field. Is the upfront validation complete? ca8210_rx_done() sets len = buf[1] + 2 and checks only an upper bound. ca8210_net_rx() then reads the DSN (data_ind[24]) before any length check: drivers/net/ieee802154/ca8210.c:ca8210_net_rx() { ... if (command[0] == SPI_MCPS_DATA_INDICATION) { spin_lock_irqsave(&priv->lock, flags); if (command[26] == priv->last_dsn) { ... return 0; } priv->last_dsn = command[26]; spin_unlock_irqrestore(&priv->lock, flags); return ca8210_skb_rx(hw, len - 2, command + 2); ... } Suppose the device sends a truncated indication with buf[1] < 25. Then command[26] is stale data or SPI_IDLE filler. It gets stored in priv->last_dsn, and ca8210_skb_rx() then rejects the frame with -EMSGSIZE. Wouldn't the next valid frame whose DSN matches that byte be silently dropped as a resend? Should the minimum length check move ahead of the command[26] access in ca8210_net_rx()? > > msdulen = data_ind[22]; /* msdu_length */ > if (msdulen > IEEE802154_MTU) { [ ... ] > @@ -1778,9 +1774,25 @@ static int ca8210_skb_rx( > &priv->spi->dev, > "received erroneously large msdu length!\n" > ); > - kfree_skb(skb); > return -EMSGSIZE; > } > + > + if (len < 30 + msdulen || > + (!priv->promiscuous && data_ind[29 + msdulen] > 0 && > + len < 29 + msdulen + sizeof(struct secspec))) { > + dev_err(&priv->spi->dev, > + "received truncated data indication!\n"); > + return -EMSGSIZE; > + } > + > + mpdulinkquality = data_ind[23]; > + > + /* Allocate mtu size buffer for every rx packet */ > + skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr)); > + if (!skb) > + return -ENOMEM; > + > + skb_reserve(skb, sizeof(hdr)); > dev_dbg(&priv->spi->dev, "skb buffer length = %d\n", msdulen); > > if (priv->promiscuous) > [Severity: High] Can priv->promiscuous change between the new truncation check and the later promiscuous test that jumps to copy_payload? With this patch ca8210_skb_rx() reads priv->promiscuous twice. The first read decides whether the secspec length condition is applied. The second read decides whether the security header is parsed: hdr.sec.level = data_ind[29 + msdulen]; if (hdr.sec.level > 0) { hdr.sec.key_id_mode = data_ind[30 + msdulen]; memcpy(&hdr.sec.extended_src, &data_ind[31 + msdulen], 8); hdr.sec.key_id = data_ind[39 + msdulen]; } ca8210_set_promiscuous_mode() writes priv->promiscuous from the mac802154 .set_promiscuous_mode callback without taking priv->lock. ca8210_skb_rx() does not hold priv->lock either, because ca8210_net_rx() drops it before the call. The two reads are also separated by dev_alloc_skb() and dev_dbg(), so the compiler has to reload the field. Suppose promiscuous mode is switched off between the two reads, and the frame has len == 30 + msdulen and a non-zero security level. The frame passes the new check with the secspec condition skipped. It then falls through into the security header parsing, which reads data_ind[30 + msdulen] .. data_ind[39 + msdulen]. That is up to 10 bytes past len, and those stale bytes end up in the MAC header pushed onto the skb. This is exactly the access the new check is meant to prevent. Would it be better to sample the flag once, for example with a local bool promiscuous = READ_ONCE(priv->promiscuous) at the top of the function? That local could then be used for both the length check and the goto to copy_payload. -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260924062244.2444225-1-benquike%40gmail.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses
@ 2026-09-30 7:19 Hui Peng
2026-09-30 7:19 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng
0 siblings, 1 reply; 10+ messages in thread
From: Hui Peng @ 2026-09-30 7:19 UTC (permalink / raw)
To: Harry Morris, Alexander Aring, Miquel Raynal, Stefan Schmidt
Cc: David Laight, linux-wpan, netdev, linux-kernel, stable, Hui Peng
This series fixes three out-of-bounds access bugs in the Cascoda CA8210
IEEE 802.15.4 driver:
1. Reject received SPI packets with len > sizeof(struct mac_message) in
ca8210_rx_done() instead of checking len > CA8210_SPI_BUF_SIZE (256),
preventing a stack buffer overflow when copying a synchronous response
into priv->sync_command_response (a struct mac_message on the caller's
stack) and matching the actual SPI transfer length
(cas_ctl->transfer.len = sizeof(struct mac_message)).
2. Initialize lenvar = 1 in ca8210_get_ed() and validate
hw_attribute_length against *hw_attribute_length in
hwme_get_request_sync() before memcpy() to prevent overflowing the
caller's stack buffer.
3. Validate the received SPI frame length len upfront at the start of
ca8210_skb_rx() before reading data_ind or allocating the skb.
Changes in v3:
- Patch 1/3: Check len > sizeof(struct mac_message) in ca8210_rx_done()
where dev_crit() logs "Received packet len (%u) erroneously long" and
drops the packet, instead of silently truncating the memcpy() with
min_t(), addressing David Laight's feedback.
Changes in v2:
- Split the ca8210 fixes into three single-issue patches (1/3..3/3) and
addressed Miquel Raynal's review comments on patches 2/3 and 3/3.
Hui Peng (3):
ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done()
ieee802154: ca8210: prevent stack buffer overflow in
hwme_get_request_sync()
ieee802154: ca8210: validate data_ind length upfront in
ca8210_skb_rx()
drivers/net/ieee802154/ca8210.c | 39 +++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 12 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() 2026-09-30 7:19 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng @ 2026-09-30 7:19 ` Hui Peng 2026-10-04 7:39 ` netdev-bot+sashiko 2026-10-04 21:00 ` Miquel Raynal 0 siblings, 2 replies; 10+ messages in thread From: Hui Peng @ 2026-09-30 7:19 UTC (permalink / raw) To: Harry Morris, Alexander Aring, Miquel Raynal, Stefan Schmidt Cc: David Laight, linux-wpan, netdev, linux-kernel, stable, Hui Peng In ca8210_spi_transfer(), each SPI transfer reads sizeof(struct mac_message) bytes into cas_ctl->tx_in_buf: cas_ctl->transfer.len = sizeof(struct mac_message); However, ca8210_rx_done() only checks the received packet length len = buf[1] + 2 against CA8210_SPI_BUF_SIZE (256). When buf[0] & SPI_SYN is set and priv->sync_command_response is non-NULL, memcpy() copies up to 256 bytes into priv->sync_command_response, which points to a struct mac_message object on the synchronous caller's stack, overflowing the stack buffer: BUG: KASAN: stack-out-of-bounds in ca8210_rx_done+0x117/0x6c0 Write of size 256 at addr ffff8881009e7c40 by task swapper/0/1 Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x125/0x200 __asan_memcpy+0x3c/0x60 ca8210_rx_done+0x117/0x6c0 ... This frame has 1 object: [32, 182) 'response' Check len > sizeof(struct mac_message) instead of len > CA8210_SPI_BUF_SIZE in ca8210_rx_done() so that any packet exceeding sizeof(struct mac_message) is logged as erroneously long via dev_crit() and dropped before copying into priv->sync_command_response or passing it to ca8210_net_rx(). Tested in QEMU with KASAN enabled by passing a 256-byte SPI_SYN response into ca8210_rx_done(). Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v3: - Check len > sizeof(struct mac_message) at the top of ca8210_rx_done() where dev_crit() logs the error and drops the packet instead of silently truncating memcpy() with min_t(), addressing David Laight's feedback. Changes in v2: - Split the ca8210 fixes into three single-issue patches (1/3..3/3). drivers/net/ieee802154/ca8210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 01af4f9..a990a0f 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -686,7 +686,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl) buf = cas_ctl->tx_in_buf; len = buf[1] + 2; - if (len > CA8210_SPI_BUF_SIZE) { + if (len > sizeof(struct mac_message)) { dev_crit( &priv->spi->dev, "Received packet len (%u) erroneously long\n", -- 2.49.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() 2026-09-30 7:19 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng @ 2026-10-04 7:39 ` netdev-bot+sashiko 2026-10-04 21:00 ` Miquel Raynal 1 sibling, 0 replies; 10+ messages in thread From: netdev-bot+sashiko @ 2026-10-04 7:39 UTC (permalink / raw) To: benquike Cc: h.morris, alex.aring, miquel.raynal, stefan, david.laight.linux, linux-wpan, netdev, linux-kernel, stable, kuba Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider. Critical: 0 · High: 1 (2) · Medium: 0 · Low: 0 (1) If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] ieee802154: ca8210: dropped Rx frames and log flood DoS due to length limit Pre-existing issues: - [High] priv->sync_command_response is a plain pointer to a synchronous caller's on-stack struct mac_message, and nothing synchronizes access… - [High] ca8210_rx_done() calls msleep(2000) (line 718) and then kmalloc_obj(*mlme_reset_wpc) (line 723, default GFP_KERNEL) when it… - [Low] Baseline decision: not reported (preexisting, low impact, outside the bug class the commit claims to fix). -- ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() This patch changes the length check in ca8210_rx_done() so that it compares against sizeof(struct mac_message) instead of CA8210_SPI_BUF_SIZE. A response that is too long is now logged and dropped. It is no longer copied into the synchronous caller's on-stack response buffer or passed to ca8210_net_rx(). > diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c > index 01af4f9cf7f29..a990a0f347ad8 100644 > --- a/drivers/net/ieee802154/ca8210.c > +++ b/drivers/net/ieee802154/ca8210.c > @@ -686,7 +686,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl) > > buf = cas_ctl->tx_in_buf; > len = buf[1] + 2; > - if (len > CA8210_SPI_BUF_SIZE) { > + if (len > sizeof(struct mac_message)) { > dev_crit( > &priv->spi->dev, > "Received packet len (%u) erroneously long\n", [Severity: High] Does this new limit also drop legitimate MCPS-DATA.indication frames? The check sits at the top of ca8210_rx_done(), so it applies to every message from the device. It is not limited to the synchronous responses that get copied into priv->sync_command_response. ca8210_net_rx() passes SPI_MCPS_DATA_INDICATION payloads to ca8210_skb_rx() as buf + 2. ca8210_skb_rx() then reads the security spec that follows the MSDU: hdr.sec.level = data_ind[29 + msdulen]; ... if (hdr.sec.level > 0) { hdr.sec.key_id_mode = data_ind[30 + msdulen]; memcpy(&hdr.sec.extended_src, &data_ind[31 + msdulen], 8); hdr.sec.key_id = data_ind[39 + msdulen]; } That makes a full indication 42 + msdulen bytes. With a 127-byte MSDU (IEEE802154_MTU), the device reports len = 169. That is larger than sizeof(struct mac_message), which is 150 according to the KASAN report in the changelog. If I read this right, any received frame with more than 108 bytes of payload is now discarded. Each dropped frame also triggers a dev_crit() with no rate limiting. Anyone in radio range can send long frames, so a remote peer could flood the kernel log this way. Should this at least use dev_crit_ratelimited() or dev_err_ratelimited()? ca8210_spi_transfer() only clocks in sizeof(struct mac_message) bytes. So before this patch, the tail of a long indication may already have come from stale tx_in_buf contents. Would it be better to keep the generic limit here, and check against sizeof(struct mac_message) only before the memcpy() into priv->sync_command_response? Or should the transfer length be sized to cover the largest MCPS-DATA.indication? Either way, dropping long data frames on stable kernels looks like a regression worth avoiding. [Severity: High] This is a pre-existing issue, but since this patch is about the memcpy() into priv->sync_command_response, can the pointer itself go stale? Later in ca8210_rx_done(), the pointer is checked and then written through. No lock or barrier protects it: drivers/net/ieee802154/ca8210.c:ca8210_rx_done() { ... if (buf[0] & SPI_SYN) { if (priv->sync_command_response) { memcpy(priv->sync_command_response, buf, len); complete(&priv->sync_exchange_complete); ... } ca8210_spi_exchange() stores a pointer to the caller's stack buffer. It then waits with an interruptible timeout. On timeout or signal, it clears the pointer and returns: drivers/net/ieee802154/ca8210.c:ca8210_spi_exchange() { ... priv->sync_command_response = response; ... wait_remaining = wait_for_completion_interruptible_timeout( &priv->sync_exchange_complete, msecs_to_jiffies(CA8210_SYNC_TIMEOUT) ); ... cleanup: priv->sync_command_response = NULL; return status; } Suppose the device response arrives just as the waiter times out or gets a signal. Could this interleaving happen? CPU1 (SPI completion) ca8210_spi_transfer_complete() ca8210_rx_done() if (priv->sync_command_response) <- sees the caller's buffer CPU2 (a sync caller such as mlme_reset_request_sync()) ca8210_spi_exchange() wait_for_completion_interruptible_timeout() returns 0 or -ERESTARTSYS priv->sync_command_response = NULL; returns, and the on-stack response buffer goes out of scope CPU1 memcpy(priv->sync_command_response, buf, len); That would write up to sizeof(struct mac_message) bytes supplied by the device into a stack frame that the caller no longer owns. Also, ca8210_spi_exchange() callers are not serialized by any mutex. Can two concurrent synchronous callers overwrite each other's sync_command_response and sync_exchange_complete? If so, one caller's reply could land in the other caller's buffer. [Severity: High] This isn't a bug introduced by this patch, but can ca8210_rx_done() sleep in a context where sleeping is not allowed? The only caller of ca8210_rx_done() is ca8210_spi_transfer_complete(). ca8210_spi_transfer() installs that function as the spi_async() completion callback: cas_ctl->msg.complete = ca8210_spi_transfer_complete; ... status = spi_async(spi, &cas_ctl->msg); The spi_async() kernel-doc in drivers/spi/spi.c says: * The completion callback is invoked in a context which can't sleep. When ca8210_rx_done() receives SPI_MCPS_DATA_CONFIRM with IEEE802154_TRANSACTION_OVERFLOW, it does this: if (buf[3] == IEEE802154_TRANSACTION_OVERFLOW) { ... msleep(2000); ... mlme_reset_wpc = kmalloc_obj(*mlme_reset_wpc); Some controllers finalize messages from IRQ or tasklet context. Would this trigger "scheduling while atomic" there? Other controllers finalize from the message pump kthread. There, it looks like this would stall the SPI bus for two seconds. [Severity: Low] This is a pre-existing issue, but ca8210_spi_transfer_complete() dumps the received buffer using the device's length byte without checking it. That happens before ca8210_rx_done() reaches the new check: if (duplex_rx) { dev_dbg(&priv->spi->dev, "READ CMD DURING TX\n"); for (i = 0; i < cas_ctl->tx_in_buf[1] + 2; i++) dev_dbg( &priv->spi->dev, "%#03x\n", cas_ctl->tx_in_buf[i] ); ca8210_rx_done(cas_ctl); } If tx_in_buf[1] == 0xff, does i reach 256 and read tx_in_buf[256]? That is one byte past the end of the CA8210_SPI_BUF_SIZE array. This only happens when the dev_dbg() call site is enabled. The loop also prints bytes beyond the sizeof(struct mac_message) bytes that the transfer actually received. Should this loop be limited to sizeof(struct mac_message) as well? -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260930071914.421586-1-benquike%40gmail.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() 2026-09-30 7:19 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng 2026-10-04 7:39 ` netdev-bot+sashiko @ 2026-10-04 21:00 ` Miquel Raynal 1 sibling, 0 replies; 10+ messages in thread From: Miquel Raynal @ 2026-10-04 21:00 UTC (permalink / raw) To: Hui Peng Cc: Harry Morris, Alexander Aring, Stefan Schmidt, David Laight, linux-wpan, netdev, linux-kernel, stable > Check len > sizeof(struct mac_message) instead of > len > CA8210_SPI_BUF_SIZE in ca8210_rx_done() so that any packet exceeding > sizeof(struct mac_message) is logged as erroneously long via dev_crit() > and dropped before copying into priv->sync_command_response or passing it > to ca8210_net_rx(). > > Tested in QEMU with KASAN enabled by passing a 256-byte SPI_SYN response > into ca8210_rx_done(). > > Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") > Cc: stable@vger.kernel.org > Assisted-by: LLM > Signed-off-by: Hui Peng <benquike@gmail.com> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses
@ 2026-09-22 9:30 Hui Peng
2026-09-22 9:30 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng
0 siblings, 1 reply; 10+ messages in thread
From: Hui Peng @ 2026-09-22 9:30 UTC (permalink / raw)
To: Harry Morris, Alexander Aring, Miquel Raynal, Stefan Schmidt
Cc: Hui Peng, David Laight, linux-wpan, netdev, linux-kernel, stable
This series fixes three out-of-bounds access bugs in the Cascoda CA8210
IEEE 802.15.4 driver:
1. Reject received SPI packets with len > sizeof(struct mac_message) in
ca8210_rx_done() instead of checking len > CA8210_SPI_BUF_SIZE (256),
preventing a stack buffer overflow when copying a synchronous response
into priv->sync_command_response (a struct mac_message on the caller's
stack) and matching the actual SPI transfer length
(cas_ctl->transfer.len = sizeof(struct mac_message)).
2. Initialize lenvar = 1 in ca8210_get_ed() and validate
hw_attribute_length against *hw_attribute_length in
hwme_get_request_sync() before memcpy() to prevent overflowing the
caller's stack buffer.
3. Validate the received SPI frame length len upfront at the start of
ca8210_skb_rx() before reading data_ind or allocating the skb.
Changes in v3:
- Patch 1/3: Check len > sizeof(struct mac_message) in ca8210_rx_done()
where dev_crit() logs "Received packet len (%u) erroneously long" and
drops the packet, instead of silently truncating the memcpy() with
min_t(), addressing David Laight's feedback.
Changes in v2:
- Split the ca8210 fixes into three single-issue patches (1/3..3/3) and
addressed Miquel Raynal's review comments on patches 2/3 and 3/3.
Hui Peng (3):
ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done()
ieee802154: ca8210: prevent stack buffer overflow in
hwme_get_request_sync()
ieee802154: ca8210: validate data_ind length upfront in
ca8210_skb_rx()
drivers/net/ieee802154/ca8210.c | 39 +++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 12 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() 2026-09-22 9:30 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng @ 2026-09-22 9:30 ` Hui Peng 0 siblings, 0 replies; 10+ messages in thread From: Hui Peng @ 2026-09-22 9:30 UTC (permalink / raw) To: Harry Morris, Alexander Aring, Miquel Raynal, Stefan Schmidt Cc: Hui Peng, David Laight, linux-wpan, netdev, linux-kernel, stable In ca8210_spi_transfer(), each SPI transfer reads sizeof(struct mac_message) bytes into cas_ctl->tx_in_buf: cas_ctl->transfer.len = sizeof(struct mac_message); However, ca8210_rx_done() only checks the received packet length len = buf[1] + 2 against CA8210_SPI_BUF_SIZE (256). When buf[0] & SPI_SYN is set and priv->sync_command_response is non-NULL, memcpy() copies up to 256 bytes into priv->sync_command_response, which points to a struct mac_message object on the synchronous caller's stack, overflowing the stack buffer: BUG: KASAN: stack-out-of-bounds in ca8210_rx_done+0x117/0x6c0 Write of size 256 at addr ffff8881009e7c40 by task swapper/0/1 Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x125/0x200 __asan_memcpy+0x3c/0x60 ca8210_rx_done+0x117/0x6c0 ... This frame has 1 object: [32, 182) 'response' Check len > sizeof(struct mac_message) instead of len > CA8210_SPI_BUF_SIZE in ca8210_rx_done() so that any packet exceeding sizeof(struct mac_message) is logged as erroneously long via dev_crit() and dropped before copying into priv->sync_command_response or passing it to ca8210_net_rx(). Tested in QEMU with KASAN enabled by passing a 256-byte SPI_SYN response into ca8210_rx_done(). Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng <benquike@gmail.com> --- Changes in v3: - Check len > sizeof(struct mac_message) at the top of ca8210_rx_done() where dev_crit() logs the error and drops the packet instead of silently truncating memcpy() with min_t(), addressing David Laight's feedback. Changes in v2: - Split the ca8210 fixes into three single-issue patches (1/3..3/3). drivers/net/ieee802154/ca8210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 01af4f9..a990a0f 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -686,7 +686,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl) buf = cas_ctl->tx_in_buf; len = buf[1] + 2; - if (len > CA8210_SPI_BUF_SIZE) { + if (len > sizeof(struct mac_message)) { dev_crit( &priv->spi->dev, "Received packet len (%u) erroneously long\n", -- 2.49.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-10-04 21:00 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-24 6:22 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng 2026-09-24 6:22 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng 2026-09-24 6:22 ` [PATCH net v3 2/3] ieee802154: ca8210: prevent stack buffer overflow in hwme_get_request_sync() Hui Peng 2026-09-28 6:42 ` netdev-bot+sashiko 2026-09-24 6:22 ` [PATCH net v3 3/3] ieee802154: ca8210: validate data_ind length upfront in ca8210_skb_rx() Hui Peng 2026-09-28 6:42 ` netdev-bot+sashiko -- strict thread matches above, loose matches on Subject: below -- 2026-09-30 7:19 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng 2026-09-30 7:19 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng 2026-10-04 7:39 ` netdev-bot+sashiko 2026-10-04 21:00 ` Miquel Raynal 2026-09-22 9:30 [PATCH net v3 0/3] ieee802154: ca8210: fix stack and slab out-of-bounds accesses Hui Peng 2026-09-22 9:30 ` [PATCH net v3 1/3] ieee802154: ca8210: prevent stack buffer overflow in ca8210_rx_done() Hui Peng
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox