Commit d793458c authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

nfc: rawsock: cancel tx_work before socket teardown



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: 23b7869c ("NFC: add the NFC socket raw protocol")
Reviewed-by: default avatarJoe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260303162346.2071888-6-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0efdc02f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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);