nfc: Fix potential resource leaks
authorMiaoqian Lin <linmq006@gmail.com>
Fri, 23 Dec 2022 07:37:18 +0000 (11:37 +0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Jan 2023 10:59:10 +0000 (11:59 +0100)
[ Upstream commit df49908f3c52d211aea5e2a14a93bbe67a2cb3af ]

nfc_get_device() take reference for the device, add missing
nfc_put_device() to release it when not need anymore.
Also fix the style warnning by use error EOPNOTSUPP instead of
ENOTSUPP.

Fixes: 5ce3f32b5264 ("NFC: netlink: SE API implementation")
Fixes: 29e76924cf08 ("nfc: netlink: Add capability to reply to vendor_cmd with data")
Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/nfc/netlink.c

index a207f0b..d928d5a 100644 (file)
@@ -1497,6 +1497,7 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info)
        u32 dev_idx, se_idx;
        u8 *apdu;
        size_t apdu_len;
+       int rc;
 
        if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
            !info->attrs[NFC_ATTR_SE_INDEX] ||
@@ -1510,25 +1511,37 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info)
        if (!dev)
                return -ENODEV;
 
-       if (!dev->ops || !dev->ops->se_io)
-               return -ENOTSUPP;
+       if (!dev->ops || !dev->ops->se_io) {
+               rc = -EOPNOTSUPP;
+               goto put_dev;
+       }
 
        apdu_len = nla_len(info->attrs[NFC_ATTR_SE_APDU]);
-       if (apdu_len == 0)
-               return -EINVAL;
+       if (apdu_len == 0) {
+               rc = -EINVAL;
+               goto put_dev;
+       }
 
        apdu = nla_data(info->attrs[NFC_ATTR_SE_APDU]);
-       if (!apdu)
-               return -EINVAL;
+       if (!apdu) {
+               rc = -EINVAL;
+               goto put_dev;
+       }
 
        ctx = kzalloc(sizeof(struct se_io_ctx), GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto put_dev;
+       }
 
        ctx->dev_idx = dev_idx;
        ctx->se_idx = se_idx;
 
-       return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
+       rc = nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
+
+put_dev:
+       nfc_put_device(dev);
+       return rc;
 }
 
 static int nfc_genl_vendor_cmd(struct sk_buff *skb,
@@ -1551,14 +1564,21 @@ static int nfc_genl_vendor_cmd(struct sk_buff *skb,
        subcmd = nla_get_u32(info->attrs[NFC_ATTR_VENDOR_SUBCMD]);
 
        dev = nfc_get_device(dev_idx);
-       if (!dev || !dev->vendor_cmds || !dev->n_vendor_cmds)
+       if (!dev)
                return -ENODEV;
 
+       if (!dev->vendor_cmds || !dev->n_vendor_cmds) {
+               err = -ENODEV;
+               goto put_dev;
+       }
+
        if (info->attrs[NFC_ATTR_VENDOR_DATA]) {
                data = nla_data(info->attrs[NFC_ATTR_VENDOR_DATA]);
                data_len = nla_len(info->attrs[NFC_ATTR_VENDOR_DATA]);
-               if (data_len == 0)
-                       return -EINVAL;
+               if (data_len == 0) {
+                       err = -EINVAL;
+                       goto put_dev;
+               }
        } else {
                data = NULL;
                data_len = 0;
@@ -1573,10 +1593,14 @@ static int nfc_genl_vendor_cmd(struct sk_buff *skb,
                dev->cur_cmd_info = info;
                err = cmd->doit(dev, data, data_len);
                dev->cur_cmd_info = NULL;
-               return err;
+               goto put_dev;
        }
 
-       return -EOPNOTSUPP;
+       err = -EOPNOTSUPP;
+
+put_dev:
+       nfc_put_device(dev);
+       return err;
 }
 
 /* message building helper */