Raw LLCP sockets own the reference returned by nfc_llcp_find_local(). When the bound NFC device is unregistered, nfc_llcp_socket_release() sets raw sockets back to LLCP_CLOSED. It also unlinks them from local->raw_sockets, but leaves llcp_sock->local pointing at that local. A subsequent successful bind on the same socket gets a new local reference and overwrites llcp_sock->local. The old local reference is then lost, and the final socket release only drops the new local. Drop any stale local reference after the new target local has been found, but before overwriting llcp_sock->local. This keeps failed bind attempts from changing the old reference while preventing a successful rebind from leaking it. Fixes: e6a3a4bb856a ("NFC: llcp: Clean raw sockets from nfc_llcp_socket_release") Cc: stable@vger.kernel.org Signed-off-by: Shuangpeng Bai --- net/nfc/llcp_sock.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index feab29fc6..0c00cdaab 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -152,6 +152,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr_unsized *addr struct sock *sk = sock->sk; struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); struct nfc_llcp_local *local; + struct nfc_llcp_local *old_local; struct nfc_dev *dev; struct sockaddr_nfc_llcp llcp_addr; int len, ret = 0; @@ -185,6 +186,11 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr_unsized *addr goto put_dev; } + old_local = llcp_sock->local; + llcp_sock->local = NULL; + llcp_sock->dev = NULL; + nfc_llcp_local_put(old_local); + llcp_sock->dev = dev; llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; -- 2.43.0