Zero allocations before they're passed to drivers to be filled out with statistics. While many drivers always correctly fill out the entire allocated space, under some failure conditions some drivers will not clear the allocated space appropriately. Unprivileged users could induce some of these failure conditions to leak kernel memory. Instead of fixing drivers one by one, the best solution is to eliminate the possibility of driver errors leaking kernel memory entirely.
Given that ethtool_get_stats(), ethtool_get_phy_stats(), and ethtool_get_tunable() are accessible without CAP_NET_ADMIN they are the most important to clear to avoid memory leaks. ethtool_self_test() and ethtool_get_any_eeprom() require CAP_NET_ADMIN but were also included for completeness. Some examples of driver methods that could fail to fill out memory: enic_get_ethtool_stats(), cp_get_ethtool_stats(), mv88e6xxx_get_ethtool_stats(), bnx2x_self_test(), be_self_test(), etc. Signed-off-by: Vlad Tsyrklevich <v...@tsyrklevich.net> --- net/core/ethtool.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 9774898..7202915 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1538,7 +1538,7 @@ static int ethtool_get_any_eeprom(struct net_device *dev, void __user *useraddr, if (eeprom.offset + eeprom.len > total_len) return -EINVAL; - data = kmalloc(PAGE_SIZE, GFP_USER); + data = kzalloc(PAGE_SIZE, GFP_USER); if (!data) return -ENOMEM; @@ -1775,7 +1775,7 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr) return -EFAULT; test.len = test_len; - data = kmalloc(test_len * sizeof(u64), GFP_USER); + data = kcalloc(test_len, sizeof(u64), GFP_USER); if (!data) return -ENOMEM; @@ -1907,7 +1907,7 @@ 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); + data = kcalloc(n_stats, sizeof(u64), GFP_USER); if (!data) return -ENOMEM; @@ -1946,7 +1946,7 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr) return -EFAULT; stats.n_stats = n_stats; - data = kmalloc_array(n_stats, sizeof(u64), GFP_USER); + data = kcalloc(n_stats, sizeof(u64), GFP_USER); if (!data) return -ENOMEM; @@ -2269,7 +2269,7 @@ static int ethtool_get_tunable(struct net_device *dev, void __user *useraddr) ret = ethtool_tunable_valid(&tuna); if (ret) return ret; - data = kmalloc(tuna.len, GFP_USER); + data = kzalloc(tuna.len, GFP_USER); if (!data) return -ENOMEM; ret = ops->get_tunable(dev, &tuna, data); -- 2.7.0