diff options
author | Michal Kubecek <mkubecek@suse.cz> | 2020-03-22 22:24:21 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-24 05:50:14 +0100 |
commit | 2f599ec422ad6634fb5ad43748b9969ca9d742bd (patch) | |
tree | 100399068cdeafc3d9e050e2f52a95b0938813aa /net/ethtool/wol.c | |
parent | net: dsa: Fix duplicate frames flooded by learning (diff) | |
download | linux-2f599ec422ad6634fb5ad43748b9969ca9d742bd.tar.xz linux-2f599ec422ad6634fb5ad43748b9969ca9d742bd.zip |
ethtool: fix reference leak in some *_SET handlers
Andrew noticed that some handlers for *_SET commands leak a netdev
reference if required ethtool_ops callbacks do not exist. A simple
reproducer would be e.g.
ip link add veth1 type veth peer name veth2
ethtool -s veth1 wol g
ip link del veth1
Make sure dev_put() is called when ethtool_ops check fails.
v2: add Fixes tags
Fixes: a53f3d41e4d3 ("ethtool: set link settings with LINKINFO_SET request")
Fixes: bfbcfe2032e7 ("ethtool: set link modes related data with LINKMODES_SET request")
Fixes: e54d04e3afea ("ethtool: set message mask with DEBUG_SET request")
Fixes: 8d425b19b305 ("ethtool: set wake-on-lan settings with WOL_SET request")
Reported-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r-- | net/ethtool/wol.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/net/ethtool/wol.c b/net/ethtool/wol.c index e1b8a65b64c4..55e1ecaaf739 100644 --- a/net/ethtool/wol.c +++ b/net/ethtool/wol.c @@ -128,8 +128,9 @@ int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info) if (ret < 0) return ret; dev = req_info.dev; + ret = -EOPNOTSUPP; if (!dev->ethtool_ops->get_wol || !dev->ethtool_ops->set_wol) - return -EOPNOTSUPP; + goto out_dev; rtnl_lock(); ret = ethnl_ops_begin(dev); @@ -172,6 +173,7 @@ out_ops: ethnl_ops_complete(dev); out_rtnl: rtnl_unlock(); +out_dev: dev_put(dev); return ret; } |