summaryrefslogtreecommitdiff
path: root/net/ethtool/netlink.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2025-06-23 16:17:14 -0700
committerJakub Kicinski <kuba@kernel.org>2025-06-25 15:24:13 -0700
commitceca0769e87ff4e33e8dab9c0277646da6d422fe (patch)
treec3d0204309aa2b416fee8508f0cd0e3b85e2fe2f /net/ethtool/netlink.c
parent826334359eacc1b70e9752ebc4954ed775dd40ca (diff)
net: ethtool: dynamically allocate full req size req
In preparation for using req_info to carry parameters between SET and NTF allocate a full request info struct. Since the size depends on the subcommand we need to allocate it on the heap. Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Link: https://patch.msgid.link/20250623231720.3124717-3-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ethtool/netlink.c')
-rw-r--r--net/ethtool/netlink.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 9de828df46cd..a9467b96f00c 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -863,8 +863,8 @@ static int ethnl_default_done(struct netlink_callback *cb)
static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
{
const struct ethnl_request_ops *ops;
- struct ethnl_req_info req_info = {};
const u8 cmd = info->genlhdr->cmd;
+ struct ethnl_req_info *req_info;
struct net_device *dev;
int ret;
@@ -874,20 +874,24 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr))
return -EINVAL;
- ret = ethnl_parse_header_dev_get(&req_info, info->attrs[ops->hdr_attr],
+ req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+
+ ret = ethnl_parse_header_dev_get(req_info, info->attrs[ops->hdr_attr],
genl_info_net(info), info->extack,
true);
if (ret < 0)
- return ret;
+ goto out_free_req;
if (ops->set_validate) {
- ret = ops->set_validate(&req_info, info);
+ ret = ops->set_validate(req_info, info);
/* 0 means nothing to do */
if (ret <= 0)
goto out_dev;
}
- dev = req_info.dev;
+ dev = req_info->dev;
rtnl_lock();
netdev_lock_ops(dev);
@@ -902,7 +906,7 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
if (ret < 0)
goto out_free_cfg;
- ret = ops->set(&req_info, info);
+ ret = ops->set(req_info, info);
if (ret < 0)
goto out_ops;
@@ -921,7 +925,9 @@ out_tie_cfg:
netdev_unlock_ops(dev);
rtnl_unlock();
out_dev:
- ethnl_parse_header_dev_put(&req_info);
+ ethnl_parse_header_dev_put(req_info);
+out_free_req:
+ kfree(req_info);
return ret;
}