net: ethtool: not call vzalloc for zero sized memory request
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: Li RongQing <lirongqing@baidu.com> Reviewed-by: Wang Li <wangli39@baidu.com> Reviewed-by: Michal Kubecek <mkubecek@suse.cz> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c43ac97bac
commit
3d8830266f
@ -1797,11 +1797,16 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
|
|||||||
WARN_ON_ONCE(!ret);
|
WARN_ON_ONCE(!ret);
|
||||||
|
|
||||||
gstrings.len = ret;
|
gstrings.len = ret;
|
||||||
|
|
||||||
|
if (gstrings.len) {
|
||||||
data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN));
|
data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN));
|
||||||
if (gstrings.len && !data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
__ethtool_get_strings(dev, gstrings.string_set, data);
|
__ethtool_get_strings(dev, gstrings.string_set, data);
|
||||||
|
} else {
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
|
if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
|
||||||
@ -1897,11 +1902,15 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
stats.n_stats = n_stats;
|
stats.n_stats = n_stats;
|
||||||
data = vzalloc(array_size(n_stats, sizeof(u64)));
|
|
||||||
if (n_stats && !data)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
|
if (n_stats) {
|
||||||
|
data = vzalloc(array_size(n_stats, sizeof(u64)));
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
ops->get_ethtool_stats(dev, &stats, data);
|
ops->get_ethtool_stats(dev, &stats, data);
|
||||||
|
} else {
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
if (copy_to_user(useraddr, &stats, sizeof(stats)))
|
if (copy_to_user(useraddr, &stats, sizeof(stats)))
|
||||||
@ -1941,17 +1950,22 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
stats.n_stats = n_stats;
|
stats.n_stats = n_stats;
|
||||||
|
|
||||||
|
if (n_stats) {
|
||||||
data = vzalloc(array_size(n_stats, sizeof(u64)));
|
data = vzalloc(array_size(n_stats, sizeof(u64)));
|
||||||
if (n_stats && !data)
|
if (!data)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dev->phydev && !ops->get_ethtool_phy_stats) {
|
if (dev->phydev && !ops->get_ethtool_phy_stats) {
|
||||||
ret = phy_ethtool_get_stats(dev->phydev, &stats, data);
|
ret = phy_ethtool_get_stats(dev->phydev, &stats, data);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
ops->get_ethtool_phy_stats(dev, &stats, data);
|
ops->get_ethtool_phy_stats(dev, &stats, data);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
if (copy_to_user(useraddr, &stats, sizeof(stats)))
|
if (copy_to_user(useraddr, &stats, sizeof(stats)))
|
||||||
|
Loading…
Reference in New Issue
Block a user