genetlink: add policies for both doit and dumpit in ctrl_dumppolicy_start()
authorJakub Kicinski <kuba@kernel.org>
Fri, 4 Nov 2022 19:13:36 +0000 (12:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Nov 2022 12:30:16 +0000 (12:30 +0000)
Separate adding doit and dumpit policies for CTRL_CMD_GETPOLICY.
This has no effect until we actually allow do and dump to come
from different sources as netlink_policy_dump_add_policy()
does deduplication.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/netlink/genetlink.c

index 7c04df1..d0c3573 100644 (file)
@@ -1260,29 +1260,57 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb)
        ctx->rt = rt;
 
        if (tb[CTRL_ATTR_OP]) {
+               struct genl_split_ops doit, dump;
+
                ctx->single_op = true;
                ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]);
 
-               err = genl_get_cmd(ctx->op, rt, &op);
-               if (err) {
+               if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO, rt, &doit) &&
+                   genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP, rt, &dump)) {
                        NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]);
-                       return err;
+                       return -ENOENT;
                }
 
-               if (!op.policy)
-                       return -ENODATA;
+               if (doit.policy) {
+                       err = netlink_policy_dump_add_policy(&ctx->state,
+                                                            doit.policy,
+                                                            doit.maxattr);
+                       if (err)
+                               goto err_free_state;
+               }
+               if (dump.policy) {
+                       err = netlink_policy_dump_add_policy(&ctx->state,
+                                                            dump.policy,
+                                                            dump.maxattr);
+                       if (err)
+                               goto err_free_state;
+               }
 
-               return netlink_policy_dump_add_policy(&ctx->state, op.policy,
-                                                     op.maxattr);
+               if (!ctx->state)
+                       return -ENODATA;
+               return 0;
        }
 
        for (i = 0; i < genl_get_cmd_cnt(rt); i++) {
+               struct genl_split_ops doit, dumpit;
+
                genl_get_cmd_by_index(i, rt, &op);
 
-               if (op.policy) {
+               genl_cmd_full_to_split(&doit, ctx->rt, &op, GENL_CMD_CAP_DO);
+               genl_cmd_full_to_split(&dumpit, ctx->rt,
+                                      &op, GENL_CMD_CAP_DUMP);
+
+               if (doit.policy) {
+                       err = netlink_policy_dump_add_policy(&ctx->state,
+                                                            doit.policy,
+                                                            doit.maxattr);
+                       if (err)
+                               goto err_free_state;
+               }
+               if (dumpit.policy) {
                        err = netlink_policy_dump_add_policy(&ctx->state,
-                                                            op.policy,
-                                                            op.maxattr);
+                                                            dumpit.policy,
+                                                            dumpit.maxattr);
                        if (err)
                                goto err_free_state;
                }