Commit 5715a502 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'nfc-skb-leaks'



Shang XiaoJing says:

====================
nfc: Fix potential memory leak of skb

There are 6 kinds of send functions can be called by nci_send_frame():
	virtual_nci_send(),
	fdp_nci_send(),
	nxp_nci_send(),
	s3fwrn5_nci_send(),
	nfcmrvl_nci_send(),
	st_nci_send();

1. virtual_nci_send() will memleak the skb, and has been fixed before.

2. fdp_nci_send() won't free the skb no matter whether write() succeed.

3-4. nxp_nci_send() and s3fwrn5_nci_send() will only free the skb when
write() failed, however write() will not free the skb by itself for when
succeeds.

5. nfcmrvl_nci_send() will call nfcmrvl_XXX_nci_send(), where some of
them will free the skb, but nfcmrvl_i2c_nci_send() only free the skb
when i2c_master_send() return >=0, and memleak will happen when
i2c_master_send() failed in nfcmrvl_i2c_nci_send().

6. st_nci_send() will queue the skb into other list and finally be
freed.

Fix the potential memory leak of skb.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a2c65a9d 93d904a7
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -249,11 +249,19 @@ static int fdp_nci_close(struct nci_dev *ndev)
static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
{
	struct fdp_nci_info *info = nci_get_drvdata(ndev);
	int ret;

	if (atomic_dec_and_test(&info->data_pkt_counter))
		info->data_pkt_counter_cb(ndev);

	return info->phy_ops->write(info->phy, skb);
	ret = info->phy_ops->write(info->phy, skb);
	if (ret < 0) {
		kfree_skb(skb);
		return ret;
	}

	consume_skb(skb);
	return 0;
}

static int fdp_nci_request_firmware(struct nci_dev *ndev)
+6 −1
Original line number Diff line number Diff line
@@ -132,12 +132,17 @@ static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv,
			ret = -EREMOTEIO;
		} else
			ret = 0;
		kfree_skb(skb);
	}

	if (ret) {
		kfree_skb(skb);
		return ret;
	}

	consume_skb(skb);
	return 0;
}

static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
					  const void *param)
{
+5 −2
Original line number Diff line number Diff line
@@ -80,12 +80,15 @@ static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
		return -EINVAL;

	r = info->phy_ops->write(info->phy_id, skb);
	if (r < 0)
	if (r < 0) {
		kfree_skb(skb);

		return r;
	}

	consume_skb(skb);
	return 0;
}

static int nxp_nci_rf_pll_unlocked_ntf(struct nci_dev *ndev,
				       struct sk_buff *skb)
{
+6 −2
Original line number Diff line number Diff line
@@ -110,13 +110,17 @@ static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
	}

	ret = s3fwrn5_write(info, skb);
	if (ret < 0)
	if (ret < 0) {
		kfree_skb(skb);

		mutex_unlock(&info->mutex);
		return ret;
	}

	consume_skb(skb);
	mutex_unlock(&info->mutex);
	return 0;
}

static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
{
	struct s3fwrn5_info *info = nci_get_drvdata(ndev);