Memory safety / NULL pointer dereference in kernel space (PN533 UART receive path)

HIGH
torvalds/linux
Commit: c71ba669b570
Affected: v7.0-rc6 and earlier (pre-fix)
2026-04-11 08:20 UTC

Description

The commit fixes a memory-safety bug in the PN533 NFC UART driver receive path. Previously, pn532_receive_buf could consume input bytes and hand a complete frame to pn533_recv_frame() before ensuring a fresh receive skb was allocated. If a fresh skb allocation failed, the callback would return the number of bytes accepted as zero, leave recv_skb as NULL, and subsequent receive handling could dereference a NULL skb (via skb_put_u8()), leading to a kernel crash or instability. The fix allocates the receive skb lazily just before consuming the next byte and, on allocation failure, returns the number of bytes already accepted. This preserves receive accounting and avoids potential NULL dereferences. The change is a correctness bug fix with memory-safety implications in the kernel space.

Proof of Concept

Proposed PoC outline (for a controlled lab environment only): 1) Build a test kernel including this PN533 UART driver path and reproduce against a test PN533 NFC device. 2) Create memory pressure to provoke GFP_KERNEL allocation failures (e.g., trigger large allocations to exhaust memory or configure the system to make alloc_skb() return NULL under GFP_KERNEL). 3) Trigger a receive path that processes at least one byte and would normally allocate a new skb for the next byte. In the vulnerable path (pre-fix behavior), allocation failure would cause the function to return 0 while already consuming bytes, leaving recv_skb NULL and risking a NULL dereference on the next skb_put_u8(). 4) Observe the crash/dereference under the old behavior. With the fix in place, the function returns the number of bytes accepted (i), and the next receive callback will attempt allocation again, avoiding dereferencing a NULL skb. 5) Validation: In a reproduceable lab, you should see a crash in the pre-fix kernel when allocation fails, and no crash in the patched kernel. Note: Do not run this on production systems. The PoC is high-level due to reliance on kernel memory state and allocation failure conditions. If you cannot reproduce in a real kernel environment, a safe, high-level test is to simulate the logic with a kernel-like function: allocate skb only when about to consume the next byte, and on allocation failure return the number of bytes already accepted, instead of proceeding with a NULL skb.

Commit Details

Author: Pengpeng Hou

Date: 2026-04-05 00:40 UTC

Message:

nfc: pn533: allocate rx skb before consuming bytes pn532_receive_buf() reports the number of accepted bytes to the serdev core. The current code consumes bytes into recv_skb and may already hand a complete frame to pn533_recv_frame() before allocating a fresh receive buffer. If that alloc_skb() fails, the callback returns 0 even though it has already consumed bytes, and it leaves recv_skb as NULL for the next receive callback. That breaks the receive_buf() accounting contract and can also lead to a NULL dereference on the next skb_put_u8(). Allocate the receive skb lazily before consuming the next byte instead. If allocation fails, return the number of bytes already accepted. Fixes: c656aa4c27b1 ("nfc: pn533: add UART phy driver") Cc: stable@vger.kernel.org Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn> Link: https://patch.msgid.link/20260405094003.3-pn533-v2-pengpeng@iscas.ac.cn Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Triage Assessment

Vulnerability Type: Memory safety (NULL pointer dereference)

Confidence: HIGH

Reasoning:

The commit fixes a crash/undefined behavior scenario due to a NULL dereference when handling receive buffers in the PN533 UART driver. By allocating the receive skb lazily before consuming bytes and handling allocation failure gracefully, it prevents a potential memory safety vulnerability (NULL pointer dereference) that could be exploited to crash or destabilize the kernel module.

Verification Assessment

Vulnerability Type: Memory safety / NULL pointer dereference in kernel space (PN533 UART receive path)

Confidence: HIGH

Affected Versions: v7.0-rc6 and earlier (pre-fix)

Code Diff

diff --git a/drivers/nfc/pn533/uart.c b/drivers/nfc/pn533/uart.c index 1b82b7b2a5fae8..e0d67cd2ac9b8f 100644 --- a/drivers/nfc/pn533/uart.c +++ b/drivers/nfc/pn533/uart.c @@ -211,6 +211,13 @@ static size_t pn532_receive_buf(struct serdev_device *serdev, timer_delete(&dev->cmd_timeout); for (i = 0; i < count; i++) { + if (!dev->recv_skb) { + dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, + GFP_KERNEL); + if (!dev->recv_skb) + return i; + } + if (unlikely(!skb_tailroom(dev->recv_skb))) skb_trim(dev->recv_skb, 0); @@ -219,9 +226,7 @@ static size_t pn532_receive_buf(struct serdev_device *serdev, continue; pn533_recv_frame(dev->priv, dev->recv_skb, 0); - dev->recv_skb = alloc_skb(PN532_UART_SKB_BUFF_LEN, GFP_KERNEL); - if (!dev->recv_skb) - return 0; + dev->recv_skb = NULL; } return i;
← Back to Alerts View on GitHub →