mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
nfc: nci: fix double completion race in nci_data_exchange_complete
nci_close_device() and nci_rx_work can both call nci_data_exchange_complete() concurrently. After commit4527025d44("nfc: nci: fix circular locking dependency in nci_close_device") moved flush_workqueue(ndev->rx_wq) after mutex_unlock(&ndev->req_lock), rx_work is no longer serialized with the explicit completion call in the close path. Both callers read the non-NULL callback pointer and invoke rawsock_data_exchange_complete(), which calls sock_put() -- but only one sock_hold() was taken, so the second sock_put() underflows the refcount and frees the socket while it is still in use. Replace the bare clear_bit(NCI_DATA_EXCHANGE) with test_and_clear_bit() so that only the first caller proceeds to invoke the callback. Fixes:4527025d44("nfc: nci: fix circular locking dependency in nci_close_device") Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com> Link: https://patch.msgid.link/20260526103121.47957-1-kipreyyy@gmail.com Signed-off-by: David Heidelberg <david@ixit.cz>
This commit is contained in:
parent
3681252705
commit
8265a626cc
|
|
@ -46,11 +46,11 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
|
|||
timer_delete_sync(&ndev->data_timer);
|
||||
clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
|
||||
|
||||
/* Mark the exchange as done before calling the callback.
|
||||
* The callback (e.g. rawsock_data_exchange_complete) may
|
||||
* want to immediately queue another data exchange.
|
||||
*/
|
||||
clear_bit(NCI_DATA_EXCHANGE, &ndev->flags);
|
||||
/* Claim completion atomically -- both close and rx_work may race here */
|
||||
if (!test_and_clear_bit(NCI_DATA_EXCHANGE, &ndev->flags)) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
/* forward skb to nfc core */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user