* [PATCH] wifi: libertas_tf: Fix slab-out-of-bounds write in if_usb_send_fw_pkt()
@ 2026-08-25 9:24 Yang Zi
2026-08-25 14:13 ` Johan Hovold
0 siblings, 1 reply; 2+ messages in thread
From: Yang Zi @ 2026-08-25 9:24 UTC (permalink / raw)
To: johannes.berg, johan, kees; +Cc: linux-wireless, libertas-dev, linux-kernel
if_usb_send_fw_pkt() copies a firmware block into the driver's
ep_out_buf using the length taken directly from the firmware header
(fwdata->hdr.datalength) without any validation. That same untrusted
value is also used as the USB transfer length and to advance
cardp->totalbytes.
A crafted or truncated firmware image can set datalength to a huge value,
which makes the memcpy() into fwdata->data write far past the end of the
1574-byte ep_out_buf (KASAN reports a ~3.5 GiB slab-out-of-bounds write)
and, once totalbytes has run away, makes the subsequent header memcpy()
read past the end of the firmware image.
check_fwfile_format() only checks the cumulative length and never bounds
an individual block, and FW_MAX_DATA_BLK_SIZE (600) is never used.
Validate the block length in if_usb_send_fw_pkt(): reject any block whose
datalength exceeds FW_MAX_DATA_BLK_SIZE or the number of bytes remaining
in the firmware image, and return -EINVAL before the memcpy(). Also
enforce the per-block upper bound in check_fwfile_format() so that
invalid images are rejected up front.
Signed-off-by: Yang Zi <2959243019@qq.com>
---
diff --git a/drivers/net/wireless/marvell/libertas_tf/if_usb.c b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
index b85c6d783bf7..f82860b77da2 100644
--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -268,6 +268,7 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
{
struct fwdata *fwdata = cardp->ep_out_buf;
u8 *firmware = (u8 *) cardp->fw->data;
+ u32 datalength;
lbtf_deb_enter(LBTF_DEB_FW);
@@ -291,17 +292,24 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
cardp->fwlastblksent = cardp->totalbytes;
cardp->totalbytes += sizeof(struct fwheader);
- memcpy(fwdata->data, &firmware[cardp->totalbytes],
- le32_to_cpu(fwdata->hdr.datalength));
+ datalength = le32_to_cpu(fwdata->hdr.datalength);
+ if (datalength > FW_MAX_DATA_BLK_SIZE ||
+ cardp->totalbytes > cardp->fw->size ||
+ datalength > cardp->fw->size - cardp->totalbytes) {
+ lbtf_deb_usb2(&cardp->udev->dev,
+ "invalid firmware block length %u\n", datalength);
+ return -EINVAL;
+ }
- lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
- le32_to_cpu(fwdata->hdr.datalength));
+ memcpy(fwdata->data, &firmware[cardp->totalbytes], datalength);
+
+ lbtf_deb_usb2(&cardp->udev->dev, "Data length = %u\n", datalength);
fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
- cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
+ cardp->totalbytes += datalength;
usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
- le32_to_cpu(fwdata->hdr.datalength), 0);
+ datalength, 0);
if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
@@ -775,6 +783,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
blksize = le32_to_cpu(fwh->datalength);
switch (bincmd) {
case FW_HAS_DATA_TO_RECV:
+ if (blksize > FW_MAX_DATA_BLK_SIZE) {
+ exit = 1;
+ break;
+ }
offset = sizeof(struct fwheader) + blksize;
data += offset;
len += offset;
@@ -782,6 +794,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
exit = 1;
break;
case FW_HAS_LAST_BLOCK:
+ if (blksize > FW_MAX_DATA_BLK_SIZE) {
+ exit = 1;
+ break;
+ }
exit = 1;
ret = 0;
break;
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] wifi: libertas_tf: Fix slab-out-of-bounds write in if_usb_send_fw_pkt()
2026-08-25 9:24 [PATCH] wifi: libertas_tf: Fix slab-out-of-bounds write in if_usb_send_fw_pkt() Yang Zi
@ 2026-08-25 14:13 ` Johan Hovold
0 siblings, 0 replies; 2+ messages in thread
From: Johan Hovold @ 2026-08-25 14:13 UTC (permalink / raw)
To: Yang Zi; +Cc: johannes.berg, kees, linux-wireless, libertas-dev, linux-kernel
On Tue, Aug 25, 2026 at 05:24:06PM +0800, Yang Zi wrote:
> if_usb_send_fw_pkt() copies a firmware block into the driver's
> ep_out_buf using the length taken directly from the firmware header
> (fwdata->hdr.datalength) without any validation. That same untrusted
> value is also used as the USB transfer length and to advance
> cardp->totalbytes.
>
> A crafted or truncated firmware image can set datalength to a huge value,
> which makes the memcpy() into fwdata->data write far past the end of the
> 1574-byte ep_out_buf (KASAN reports a ~3.5 GiB slab-out-of-bounds write)
> and, once totalbytes has run away, makes the subsequent header memcpy()
> read past the end of the firmware image.
>
> check_fwfile_format() only checks the cumulative length and never bounds
> an individual block, and FW_MAX_DATA_BLK_SIZE (600) is never used.
>
> Validate the block length in if_usb_send_fw_pkt(): reject any block whose
> datalength exceeds FW_MAX_DATA_BLK_SIZE or the number of bytes remaining
> in the firmware image, and return -EINVAL before the memcpy(). Also
> enforce the per-block upper bound in check_fwfile_format() so that
> invalid images are rejected up front.
>
> Signed-off-by: Yang Zi <2959243019@qq.com>
Missing Assisted-by tag here too?
This patch is also corrupt and cannot be applied.
Johan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-25 14:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 9:24 [PATCH] wifi: libertas_tf: Fix slab-out-of-bounds write in if_usb_send_fw_pkt() Yang Zi
2026-08-25 14:13 ` Johan Hovold
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox