Re: [PATCH net] nfc: llcp: fix NULL pointer dereference race in nfc_llcp_send_ui_frame()
From: David Heidelberg
Date: Tue Aug 11 2026 - 14:47:35 EST
On 25/07/2026 13:55, Junwoong Doh wrote:
nfc_llcp_send_ui_frame() checks whether sock->local is NULL, but it isHello Junwoong,
called by llcp_sock_sendmsg() without the socket lock held, which opens
a window for a race condition. Between the sock->local check and the
sock->dev use in nfc_alloc_send_skb(), llcp_sock_bind() can run
concurrently and set both sock->local and sock->dev to NULL, which can
lead to a NULL pointer dereference in nfc_alloc_send_skb().
Take the socket lock in nfc_llcp_send_ui_frame() so that the sock->local
check and the sock->dev use are performed under it. The message is
copied from user space before the lock is taken, to avoid holding the
lock across a user space access that can block for an unbounded amount
of time.
Fixes: dded08927ca3 ("nfc: llcp: fix NULL error pointer dereference on sendmsg() after failed bind()")
Signed-off-by: Junwoong Doh <jdoh.kernel@xxxxxxxxx>
Link: https://lore.kernel.org/all/a89d0419-8bcf-40a2-b52d-3e5d911f11da@xxxxxxxxx/
---
net/nfc/llcp_commands.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
it seems Sashiko noted an issue, could you verify it please (see below, feel free to ignore the pre-existing one)?
Thanks
David
--- Patch [1]: [PATCH net] nfc: llcp: fix NULL pointer dereference race in nfc_llcp_send_ui_frame() ---
commit 9c4c4bdf57043772ddc74843af1f533e7e9bc0ca
Author: Junwoong Doh <jdoh.kernel@xxxxxxxxx>
nfc: llcp: fix NULL pointer dereference race in nfc_llcp_send_ui_frame()
This patch fixes a race condition in nfc_llcp_send_ui_frame() where
concurrent bind() calls can lead to a NULL pointer dereference. It moves
the allocation and socket state checks inside the socket lock.
Link: https://lore.kernel.org/all/a89d0419-8bcf-40a2-b52d-3e5d911f11da@xxxxxxxxx/
> diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
> index 291f26facbf3a..cfd5f6aebf8df 100644
> --- a/net/nfc/llcp_commands.c
> +++ b/net/nfc/llcp_commands.c
[ ... ]
> @@ -763,7 +769,7 @@ int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
> pr_debug("Fragment %zd bytes remaining %zd",
> frag_len, remaining_len);
>
> - pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, 0,
> + pdu = nfc_alloc_send_skb(sock->dev, sk, 0,
> frag_len + LLCP_HEADER_SIZE, &err);
Since the lock_sock(sk) critical section now covers this entire loop, could
calling nfc_alloc_send_skb() with a hardcoded flags value of 0 cause an
uninterruptible sleep deadlock?
When the socket's write buffer is full, sock_alloc_send_skb() will invoke
sock_wait_for_wmem() to sleep until memory is available. For datagram
sockets, this function does not drop the socket lock while sleeping.
Concurrently, any other operations needing the socket lock (such as close()
calling llcp_sock_release) might hang in a D-state indefinitely until the
send buffer drains.
> if (pdu == NULL) {
> pr_err("Could not allocate PDU (error=%d)\n", err);
> len -= remaining_len;
This is a pre-existing issue, but does the exact same race condition remain
unpatched in nfc_llcp_send_i_frame()?
In nfc_llcp_send_i_frame(), llcp_allocate_pdu() is called without holding
the socket lock. If a concurrent disconnect frame transitions the socket to
LLCP_CLOSED, a concurrent failed bind() can set llcp_sock->dev to NULL:
net/nfc/llcp_commands.c:nfc_llcp_send_i_frame() {
...
pdu = llcp_allocate_pdu(sock, LLCP_PDU_I,
frag_len + LLCP_SEQUENCE_SIZE);
...
}
Which then calls nfc_alloc_send_skb() and dereferences the nullified
sock->dev when computing the headroom:
net/nfc/core.c:nfc_alloc_send_skb() {
...
total_size = size +
dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
...
}
Would it be necessary to apply a similar locking fix to
nfc_llcp_send_i_frame() to prevent this NULL pointer dereference?