Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77b924d9 authored by Li RongQing's avatar Li RongQing Committed by Greg Kroah-Hartman
Browse files

net: ethtool: not call vzalloc for zero sized memory request



[ Upstream commit 3d8830266ffc28c16032b859e38a0252e014b631 ]

NULL or ZERO_SIZE_PTR will be returned for zero sized memory
request, and derefencing them will lead to a segfault

so it is unnecessory to call vzalloc for zero sized memory
request and not call functions which maybe derefence the
NULL allocated memory

this also fixes a possible memory leak if phy_ethtool_get_stats
returns error, memory should be freed before exit

Signed-off-by: default avatarLi RongQing <lirongqing@baidu.com>
Reviewed-by: default avatarWang Li <wangli39@baidu.com>
Reviewed-by: default avatarMichal Kubecek <mkubecek@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 69967638
Loading
Loading
Loading
Loading
+30 −17
Original line number Diff line number Diff line
@@ -1801,17 +1801,22 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)

	gstrings.len = ret;

	if (gstrings.len) {
		data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
		if (!data)
			return -ENOMEM;

		__ethtool_get_strings(dev, gstrings.string_set, data);
	} else {
		data = NULL;
	}

	ret = -EFAULT;
	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
		goto out;
	useraddr += sizeof(gstrings);
	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
	if (gstrings.len &&
	    copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
		goto out;
	ret = 0;

@@ -1899,17 +1904,21 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
		return -EFAULT;

	stats.n_stats = n_stats;
	if (n_stats) {
		data = kmalloc(n_stats * sizeof(u64), GFP_USER);
		if (!data)
			return -ENOMEM;

		ops->get_ethtool_stats(dev, &stats, data);
	} else {
		data = NULL;
	}

	ret = -EFAULT;
	if (copy_to_user(useraddr, &stats, sizeof(stats)))
		goto out;
	useraddr += sizeof(stats);
	if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
	if (n_stats && copy_to_user(useraddr, data, n_stats * sizeof(u64)))
		goto out;
	ret = 0;

@@ -1938,6 +1947,7 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
		return -EFAULT;

	stats.n_stats = n_stats;
	if (n_stats) {
		data = kmalloc_array(n_stats, sizeof(u64), GFP_USER);
		if (!data)
			return -ENOMEM;
@@ -1945,12 +1955,15 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
		mutex_lock(&phydev->lock);
		phydev->drv->get_stats(phydev, &stats, data);
		mutex_unlock(&phydev->lock);
	} else {
		data = NULL;
	}

	ret = -EFAULT;
	if (copy_to_user(useraddr, &stats, sizeof(stats)))
		goto out;
	useraddr += sizeof(stats);
	if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64)))
	if (n_stats && copy_to_user(useraddr, data, n_stats * sizeof(u64)))
		goto out;
	ret = 0;