summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLi RongQing <lirongqing@baidu.com>2019-03-29 09:18:02 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-27 09:30:26 +0200
commitc20f5d00dc422b9463fc5643c137c4d95f486b98 (patch)
tree3b4cb4588dbe0b8eee4d935c5c925f3b733d18d0 /net
parentc2bca92ba948f3def1f99f6b429ec39e07354dc2 (diff)
downloadlinux-stable-c20f5d00dc422b9463fc5643c137c4d95f486b98.tar.gz
linux-stable-c20f5d00dc422b9463fc5643c137c4d95f486b98.tar.bz2
linux-stable-c20f5d00dc422b9463fc5643c137c4d95f486b98.zip
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: 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 14bb1583947e..2a467d653bbe 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1257,17 +1257,22 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
gstrings.len = ret;
- data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
- if (!data)
- return -ENOMEM;
+ if (gstrings.len) {
+ data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
+ if (!data)
+ return -ENOMEM;
- __ethtool_get_strings(dev, gstrings.string_set, data);
+ __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;
@@ -1355,17 +1360,21 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
return -EFAULT;
stats.n_stats = n_stats;
- data = kmalloc(n_stats * sizeof(u64), GFP_USER);
- if (!data)
- return -ENOMEM;
+ if (n_stats) {
+ data = kmalloc(n_stats * sizeof(u64), GFP_USER);
+ if (!data)
+ return -ENOMEM;
- ops->get_ethtool_stats(dev, &stats, data);
+ 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;