From: Julian Wiedmann jwi@linux.ibm.com
mainline inclusion from mainline-v5.16-rc3 commit 0276af2176c78771da7f311621a25d7608045827 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7A2A0 CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
ethtool_set_coalesce() now uses both the .get_coalesce() and .set_coalesce() callbacks. But the check for their availability is buggy, so changing the coalesce settings on a device where the driver provides only _one_ of the callbacks results in a NULL pointer dereference instead of an -EOPNOTSUPP.
Fix the condition so that the availability of both callbacks is ensured. This also matches the netlink code.
Note that reproducing this requires some effort - it only affects the legacy ioctl path, and needs a specific combination of driver options: - have .get_coalesce() and .coalesce_supported but no .set_coalesce(), or - have .set_coalesce() but no .get_coalesce(). Here eg. ethtool doesn't cause the crash as it first attempts to call ethtool_get_coalesce() and bails out on error.
Fixes: f3ccfda19319 ("ethtool: extend coalesce setting uAPI with CQE mode") Cc: Yufeng Mo moyufeng@huawei.com Cc: Huazhong Tan tanhuazhong@huawei.com Cc: Andrew Lunn andrew@lunn.ch Cc: Heiner Kallweit hkallweit1@gmail.com Signed-off-by: Julian Wiedmann jwi@linux.ibm.com Link: https://lore.kernel.org/r/20211126175543.28000-1-jwi@linux.ibm.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com --- net/ethtool/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index ab056feb44a8..63a88b3e861d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1696,7 +1696,7 @@ static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, struct ethtool_coalesce coalesce; int ret;
- if (!dev->ethtool_ops->set_coalesce && !dev->ethtool_ops->get_coalesce) + if (!dev->ethtool_ops->set_coalesce || !dev->ethtool_ops->get_coalesce) return -EOPNOTSUPP;
ret = dev->ethtool_ops->get_coalesce(dev, &coalesce, &kernel_coalesce,