[PATCH] nfc: pn533: fix slab-out-of-bounds read in pn533_recv_frame()

From: Rahul Rao

Date: Wed Oct 14 2026 - 01:41:39 EST


In pn533_recv_frame(), dev->ops->rx_frame_size(skb->data) calculates
the expected frame length from the frame header, and then
print_hex_dump_debug() dumps the frame payload.

However, if an incoming USB URB delivers a malformed or truncated packet,
skb->len may be smaller than the minimum header size or smaller than the
declared frame length. When inspecting the frame or calling
print_hex_dump_debug(), this leads to an out-of-bounds read beyond the
allocated skb buffer.

Add sanity checks to verify that:
1. skb->len is at least dev->ops->rx_header_len before parsing frame sizes.
2. skb->len is at least frame_size before printing or validating the frame.

Reported-by: syzbot+93f169a8e7d66864f800@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=93f169a8e7d66864f800
Fixes: 9815c7cf22da ("NFC: pn533: Separate physical layer from the core implementation")
Signed-off-by: Rahul Rao <shreeramrahul94@xxxxxxxxx>
---
drivers/nfc/pn533/pn533.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c
index b0133e51dce9..6b0005395b95 100644
--- a/drivers/nfc/pn533/pn533.c
+++ b/drivers/nfc/pn533/pn533.c
@@ -2178,6 +2178,8 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
*/
void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status)
{
+ int frame_size;
+
if (!dev->cmd)
goto sched_wq;

@@ -2193,12 +2195,29 @@ void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status)
goto sched_wq;
}

+ /* Verify skb has enough bytes for the minimum RX header */
+ if (skb->len < dev->ops->rx_header_len) {
+ dev_err(dev->dev, "Frame too small (%d bytes)\n", skb->len);
+ dev->cmd->status = -EIO;
+ dev_kfree_skb(skb);
+ goto sched_wq;
+ }
+
if (pn533_rx_frame_is_ack(skb->data)) {
dev_dbg(dev->dev, "%s: Received ACK frame\n", __func__);
dev_kfree_skb(skb);
return;
}

+ frame_size = dev->ops->rx_frame_size(skb->data);
+ if (frame_size < 0 || skb->len < frame_size) {
+ dev_err(dev->dev, "Invalid or truncated frame (len=%d, expected=%d)\n",
+ skb->len, frame_size);
+ dev->cmd->status = -EIO;
+ dev_kfree_skb(skb);
+ goto sched_wq;
+ }
+
print_hex_dump_debug("PN533 RX: ", DUMP_PREFIX_NONE, 16, 1, skb->data,
dev->ops->rx_frame_size(skb->data), false);

--
2.43.0