diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-03-03 08:23:43 -0800 |
|---|---|---|
| committer | Sasha Levin <sashal@kernel.org> | 2026-03-12 07:09:58 -0400 |
| commit | 91ff0d8c3464da7f0c43da38c195e60b660128bf (patch) | |
| tree | 083b1cfa44966c80022fdd32c07ef784ddf43c52 | |
| parent | 9d448bbab724b94d6c561e1f314656f5b88a7cb3 (diff) | |
| download | linux-91ff0d8c3464da7f0c43da38c195e60b660128bf.tar.gz linux-91ff0d8c3464da7f0c43da38c195e60b660128bf.tar.bz2 linux-91ff0d8c3464da7f0c43da38c195e60b660128bf.zip | |
nfc: nci: complete pending data exchange on device close
[ Upstream commit 66083581945bd5b8e99fe49b5aeb83d03f62d053 ]
In nci_close_device(), complete any pending data exchange before
closing. The data exchange callback (e.g.
rawsock_data_exchange_complete) holds a socket reference.
NIPA occasionally hits this leak:
unreferenced object 0xff1100000f435000 (size 2048):
comm "nci_dev", pid 3954, jiffies 4295441245
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
27 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 '..@............
backtrace (crc ec2b3c5):
__kmalloc_noprof+0x4db/0x730
sk_prot_alloc.isra.0+0xe4/0x1d0
sk_alloc+0x36/0x760
rawsock_create+0xd1/0x540
nfc_sock_create+0x11f/0x280
__sock_create+0x22d/0x630
__sys_socket+0x115/0x1d0
__x64_sys_socket+0x72/0xd0
do_syscall_64+0x117/0xfc0
entry_SYSCALL_64_after_hwframe+0x4b/0x53
Fixes: 38f04c6b1b68 ("NFC: protect nci_data_exchange transactions")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260303162346.2071888-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
| -rw-r--r-- | net/nfc/nci/core.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index f6dc0a94b8d5..d334b7aa8c17 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -567,6 +567,10 @@ static int nci_close_device(struct nci_dev *ndev) flush_workqueue(ndev->cmd_wq); timer_delete_sync(&ndev->cmd_timer); timer_delete_sync(&ndev->data_timer); + if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) + nci_data_exchange_complete(ndev, NULL, + ndev->cur_conn_id, + -ENODEV); mutex_unlock(&ndev->req_lock); return 0; } @@ -598,6 +602,11 @@ static int nci_close_device(struct nci_dev *ndev) flush_workqueue(ndev->cmd_wq); timer_delete_sync(&ndev->cmd_timer); + timer_delete_sync(&ndev->data_timer); + + if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) + nci_data_exchange_complete(ndev, NULL, ndev->cur_conn_id, + -ENODEV); /* Clear flags except NCI_UNREG */ ndev->flags &= BIT(NCI_UNREG); |
