diff options
author | Li RongQing <lirongqing@baidu.com> | 2019-03-29 09:18:02 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-27 09:30:26 +0200 |
commit | c20f5d00dc422b9463fc5643c137c4d95f486b98 (patch) | |
tree | 3b4cb4588dbe0b8eee4d935c5c925f3b733d18d0 | |
parent | c2bca92ba948f3def1f99f6b429ec39e07354dc2 (diff) | |
download | linux-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>
-rw-r--r-- | net/core/ethtool.c | 29 |
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; |