Re: [PATCH 1/1] nfc: llcp: reject connect() on sockets not in LLCP_CLOSED state

From: Simon Horman

Date: Mon Sep 21 2026 - 10:24:29 EST


On Fri, Sep 18, 2026 at 11:39:20AM +0800, Yuchao Zhang wrote:
> When a socket is bound via llcp_sock_bind(), its state transitions to
> LLCP_BOUND and it is linked into the local->sockets hlist via
> nfc_llcp_sock_link().
>
> Currently, llcp_sock_connect() only checks if the socket is already
> connected (LLCP_CONNECTED) or in progress (LLCP_CONNECTING):
>
> if (sk->sk_state == LLCP_CONNECTED) {
> ret = -EISCONN;
> goto error;
> }
> if (sk->sk_state == LLCP_CONNECTING) {
> ret = -EINPROGRESS;
> goto error;
> }
>
> Crucially, it does not check for the LLCP_BOUND (or LLCP_LISTEN) state.
> Previous fixes addressing CVE-2020-25670 / CVE-2020-25673 added the check
> for LLCP_CONNECTING to prevent duplicate in-flight connection attempts
> from corrupting the connecting_sockets list. However, they assumed any
> other non-connected socket was in LLCP_CLOSED, leaving the LLCP_BOUND
> state window unhandled.
>
> If connect() is invoked on a socket that has already been bound:
> 1. llcp_sock_connect() silently overwrites llcp_sock->dev and
> llcp_sock->local without releasing previous references or freeing the
> bound service_name, leading to refcount and memory leaks.
> 2. The socket remains linked in local->sockets, while llcp_sock_connect()
> links it again into local->connecting_sockets via nfc_llcp_sock_link().
> 3. When connection confirmation (CC) arrives, nfc_llcp_recv_cc() executes:
>
> nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
> nfc_llcp_sock_link(&local->sockets, sk);
>
> Because sk was never unlinked from local->sockets, the head.first of
> local->sockets still points to &sk->sk_node. The second
> hlist_add_head() sets sk->sk_node.next = sk->sk_node, producing a
> self-referential loop. Subsequent traversals of local->sockets
> (e.g. nfc_llcp_sock_get(), nfc_llcp_socket_release()) enter an
> infinite loop with spinlocks held, resulting in kernel soft-lockups.
> 4. Furthermore, if connect() specifies a different NFC device index than
> bind(), the socket remains linked on device A's socket list while
> being assigned to device B, causing cross-device socket confusion.
>
> Fix this by ensuring that llcp_sock_connect() only accepts sockets in the
> LLCP_CLOSED state, returning -EBADFD otherwise, matching the state check
> behavior in llcp_sock_bind().
>
> Fixes: d646960f7986 ("NFC: Initial LLCP support")
> Signed-off-by: Yuchao Zhang <ndaugoing@xxxxxxxxx>

Reviewed-by: Simon Horman <horms@xxxxxxxxxx>