]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfc: nci: free skb on nci_transceive early error paths
authorJakub Kicinski <kuba@kernel.org>
Tue, 3 Mar 2026 16:23:41 +0000 (08:23 -0800)
committerSasha Levin <sashal@kernel.org>
Thu, 12 Mar 2026 11:09:56 +0000 (07:09 -0400)
[ Upstream commit 7bd4b0c4779f978a6528c9b7937d2ca18e936e2c ]

nci_transceive() takes ownership of the skb passed by the caller,
but the -EPROTO, -EINVAL, and -EBUSY error paths return without
freeing it.

Due to issues clearing NCI_DATA_EXCHANGE fixed by subsequent changes
the nci/nci_dev selftest hits the error path occasionally in NIPA,
and kmemleak detects leaks:

unreferenced object 0xff11000015ce6a40 (size 640):
  comm "nci_dev", pid 3954, jiffies 4295441246
  hex dump (first 32 bytes):
    6b 6b 6b 6b 00 a4 00 0c 02 e1 03 6b 6b 6b 6b 6b  kkkk.......kkkkk
    6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
  backtrace (crc 7c40cc2a):
    kmem_cache_alloc_node_noprof+0x492/0x630
    __alloc_skb+0x11e/0x5f0
    alloc_skb_with_frags+0xc6/0x8f0
    sock_alloc_send_pskb+0x326/0x3f0
    nfc_alloc_send_skb+0x94/0x1d0
    rawsock_sendmsg+0x162/0x4c0
    do_syscall_64+0x117/0xfc0

Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260303162346.2071888-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/nfc/nci/core.c

index 46681bdaeabfff1b624dea14c397fff3adffa7f1..f6dc0a94b8d5498b5fbb33aeca1f567c49aa53e0 100644 (file)
@@ -1035,18 +1035,23 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
        struct nci_conn_info *conn_info;
 
        conn_info = ndev->rf_conn_info;
-       if (!conn_info)
+       if (!conn_info) {
+               kfree_skb(skb);
                return -EPROTO;
+       }
 
        pr_debug("target_idx %d, len %d\n", target->idx, skb->len);
 
        if (!ndev->target_active_prot) {
                pr_err("unable to exchange data, no active target\n");
+               kfree_skb(skb);
                return -EINVAL;
        }
 
-       if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags))
+       if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags)) {
+               kfree_skb(skb);
                return -EBUSY;
+       }
 
        /* store cb and context to be used on receiving data */
        conn_info->data_exchange_cb = cb;