net: ethtool: Don't call .cleanup_data when prepare_data fails
[ Upstream commit 4f038a6a02d20859a3479293cbf172b0f14cbdd6 ]
There's a consistent pattern where the .cleanup_data() callback is
called when .prepare_data() fails, when it should really be called to
clean after a successful .prepare_data() as per the documentation.
Rewrite the error-handling paths to make sure we don't cleanup
un-prepared data.
Fixes: c781ff12a2 ("ethtool: Allow network drivers to dump arbitrary EEPROM data")
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20250407130511.75621-1-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
b2f3c3d57a
commit
a065b99605
@@ -490,7 +490,7 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
|
|||||||
ret = ops->prepare_data(req_info, reply_data, info);
|
ret = ops->prepare_data(req_info, reply_data, info);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_cleanup;
|
goto err_dev;
|
||||||
ret = ops->reply_size(req_info, reply_data);
|
ret = ops->reply_size(req_info, reply_data);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_cleanup;
|
goto err_cleanup;
|
||||||
@@ -548,7 +548,7 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
|
|||||||
ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
|
ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info);
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out_cancel;
|
||||||
ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
|
ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -557,6 +557,7 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
|
|||||||
out:
|
out:
|
||||||
if (ctx->ops->cleanup_data)
|
if (ctx->ops->cleanup_data)
|
||||||
ctx->ops->cleanup_data(ctx->reply_data);
|
ctx->ops->cleanup_data(ctx->reply_data);
|
||||||
|
out_cancel:
|
||||||
ctx->reply_data->dev = NULL;
|
ctx->reply_data->dev = NULL;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
genlmsg_cancel(skb, ehdr);
|
genlmsg_cancel(skb, ehdr);
|
||||||
@@ -760,7 +761,7 @@ static void ethnl_default_notify(struct net_device *dev, unsigned int cmd,
|
|||||||
ethnl_init_reply_data(reply_data, ops, dev);
|
ethnl_init_reply_data(reply_data, ops, dev);
|
||||||
ret = ops->prepare_data(req_info, reply_data, &info);
|
ret = ops->prepare_data(req_info, reply_data, &info);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_cleanup;
|
goto err_rep;
|
||||||
ret = ops->reply_size(req_info, reply_data);
|
ret = ops->reply_size(req_info, reply_data);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_cleanup;
|
goto err_cleanup;
|
||||||
@@ -795,6 +796,7 @@ err_skb:
|
|||||||
err_cleanup:
|
err_cleanup:
|
||||||
if (ops->cleanup_data)
|
if (ops->cleanup_data)
|
||||||
ops->cleanup_data(reply_data);
|
ops->cleanup_data(reply_data);
|
||||||
|
err_rep:
|
||||||
kfree(reply_data);
|
kfree(reply_data);
|
||||||
kfree(req_info);
|
kfree(req_info);
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user