]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: ethtool: dynamically allocate full req size req
authorJakub Kicinski <kuba@kernel.org>
Mon, 23 Jun 2025 23:17:14 +0000 (16:17 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 25 Jun 2025 22:24:13 +0000 (15:24 -0700)
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>
net/ethtool/netlink.c

index 9de828df46cd3728d9bae283e98b348cdd28cbc1..a9467b96f00ce68bd8d41b8be0b0dc458af53e2d 100644 (file)
@@ -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;
 }