Skip to content

Commit 2f599ec

Browse files
mkubecekdavem330
authored andcommitted
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: a53f3d4 ("ethtool: set link settings with LINKINFO_SET request") Fixes: bfbcfe2 ("ethtool: set link modes related data with LINKMODES_SET request") Fixes: e54d04e ("ethtool: set message mask with DEBUG_SET request") Fixes: 8d425b1 ("ethtool: set wake-on-lan settings with WOL_SET request") Reported-by: Andrew Lunn <[email protected]> Signed-off-by: Michal Kubecek <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0e62f54 commit 2f599ec

File tree

4 files changed

+12
-4
lines changed

4 files changed

+12
-4
lines changed

net/ethtool/debug.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
107107
if (ret < 0)
108108
return ret;
109109
dev = req_info.dev;
110+
ret = -EOPNOTSUPP;
110111
if (!dev->ethtool_ops->get_msglevel || !dev->ethtool_ops->set_msglevel)
111-
return -EOPNOTSUPP;
112+
goto out_dev;
112113

113114
rtnl_lock();
114115
ret = ethnl_ops_begin(dev);
@@ -129,6 +130,7 @@ int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info)
129130
ethnl_ops_complete(dev);
130131
out_rtnl:
131132
rtnl_unlock();
133+
out_dev:
132134
dev_put(dev);
133135
return ret;
134136
}

net/ethtool/linkinfo.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,10 @@ int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)
126126
if (ret < 0)
127127
return ret;
128128
dev = req_info.dev;
129+
ret = -EOPNOTSUPP;
129130
if (!dev->ethtool_ops->get_link_ksettings ||
130131
!dev->ethtool_ops->set_link_ksettings)
131-
return -EOPNOTSUPP;
132+
goto out_dev;
132133

133134
rtnl_lock();
134135
ret = ethnl_ops_begin(dev);
@@ -162,6 +163,7 @@ int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info)
162163
ethnl_ops_complete(dev);
163164
out_rtnl:
164165
rtnl_unlock();
166+
out_dev:
165167
dev_put(dev);
166168
return ret;
167169
}

net/ethtool/linkmodes.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,10 @@ int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)
338338
if (ret < 0)
339339
return ret;
340340
dev = req_info.dev;
341+
ret = -EOPNOTSUPP;
341342
if (!dev->ethtool_ops->get_link_ksettings ||
342343
!dev->ethtool_ops->set_link_ksettings)
343-
return -EOPNOTSUPP;
344+
goto out_dev;
344345

345346
rtnl_lock();
346347
ret = ethnl_ops_begin(dev);
@@ -370,6 +371,7 @@ int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info)
370371
ethnl_ops_complete(dev);
371372
out_rtnl:
372373
rtnl_unlock();
374+
out_dev:
373375
dev_put(dev);
374376
return ret;
375377
}

net/ethtool/wol.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,9 @@ int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info)
128128
if (ret < 0)
129129
return ret;
130130
dev = req_info.dev;
131+
ret = -EOPNOTSUPP;
131132
if (!dev->ethtool_ops->get_wol || !dev->ethtool_ops->set_wol)
132-
return -EOPNOTSUPP;
133+
goto out_dev;
133134

134135
rtnl_lock();
135136
ret = ethnl_ops_begin(dev);
@@ -172,6 +173,7 @@ int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info)
172173
ethnl_ops_complete(dev);
173174
out_rtnl:
174175
rtnl_unlock();
176+
out_dev:
175177
dev_put(dev);
176178
return ret;
177179
}

0 commit comments

Comments
 (0)