]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nfc: rawsock: cancel tx_work before socket teardown
authorJakub Kicinski <kuba@kernel.org>
Tue, 3 Mar 2026 16:23:45 +0000 (08:23 -0800)
committerJakub Kicinski <kuba@kernel.org>
Thu, 5 Mar 2026 02:18:57 +0000 (18:18 -0800)
In rawsock_release(), cancel any pending tx_work and purge the write
queue before orphaning the socket.  rawsock_tx_work runs on the system
workqueue and calls nfc_data_exchange which dereferences the NCI
device.  Without synchronization, tx_work can race with socket and
device teardown when a process is killed (e.g. by SIGKILL), leading
to use-after-free or leaked references.

Set SEND_SHUTDOWN first so that if tx_work is already running it will
see the flag and skip transmitting, then use cancel_work_sync to wait
for any in-progress execution to finish, and finally purge any
remaining queued skbs.

Fixes: 23b7869c0fd0 ("NFC: add the NFC socket raw protocol")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260303162346.2071888-6-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/nfc/rawsock.c

index b049022399aea0361fb90e77d14c0727474e0688..f7d7a599fade772bf8b91e602f6baeed1ed294a3 100644 (file)
@@ -67,6 +67,17 @@ static int rawsock_release(struct socket *sock)
        if (sock->type == SOCK_RAW)
                nfc_sock_unlink(&raw_sk_list, sk);
 
+       if (sk->sk_state == TCP_ESTABLISHED) {
+               /* Prevent rawsock_tx_work from starting new transmits and
+                * wait for any in-progress work to finish.  This must happen
+                * before the socket is orphaned to avoid a race where
+                * rawsock_tx_work runs after the NCI device has been freed.
+                */
+               sk->sk_shutdown |= SEND_SHUTDOWN;
+               cancel_work_sync(&nfc_rawsock(sk)->tx_work);
+               rawsock_write_queue_purge(sk);
+       }
+
        sock_orphan(sk);
        sock_put(sk);