genetlink: support split policies in ctrl_dumppolicy_put_op()
authorJakub Kicinski <kuba@kernel.org>
Fri, 4 Nov 2022 19:13:37 +0000 (12:13 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 7 Nov 2022 12:30:16 +0000 (12:30 +0000)
Pass do and dump versions of the op to ctrl_dumppolicy_put_op()
so that it can provide a different policy index for the two.

Since we now look at policies, and those are set appropriately
there's no need to look at the GENL_DONT_VALIDATE_DUMP flag.

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 d0c3573..93e33e2 100644 (file)
@@ -1345,7 +1345,8 @@ static void *ctrl_dumppolicy_prep(struct sk_buff *skb,
 
 static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
                                  struct netlink_callback *cb,
-                                 struct genl_ops *op)
+                                 struct genl_split_ops *doit,
+                                 struct genl_split_ops *dumpit)
 {
        struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx;
        struct nlattr *nest_pol, *nest_op;
@@ -1353,10 +1354,7 @@ static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
        int idx;
 
        /* skip if we have nothing to show */
-       if (!op->policy)
-               return 0;
-       if (!op->doit &&
-           (!op->dumpit || op->validate & GENL_DONT_VALIDATE_DUMP))
+       if (!doit->policy && !dumpit->policy)
                return 0;
 
        hdr = ctrl_dumppolicy_prep(skb, cb);
@@ -1367,21 +1365,26 @@ static int ctrl_dumppolicy_put_op(struct sk_buff *skb,
        if (!nest_pol)
                goto err;
 
-       nest_op = nla_nest_start(skb, op->cmd);
+       nest_op = nla_nest_start(skb, doit->cmd);
        if (!nest_op)
                goto err;
 
-       /* for now both do/dump are always the same */
-       idx = netlink_policy_dump_get_policy_idx(ctx->state,
-                                                op->policy,
-                                                op->maxattr);
+       if (doit->policy) {
+               idx = netlink_policy_dump_get_policy_idx(ctx->state,
+                                                        doit->policy,
+                                                        doit->maxattr);
 
-       if (op->doit && nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx))
-               goto err;
+               if (nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx))
+                       goto err;
+       }
+       if (dumpit->policy) {
+               idx = netlink_policy_dump_get_policy_idx(ctx->state,
+                                                        dumpit->policy,
+                                                        dumpit->maxattr);
 
-       if (op->dumpit && !(op->validate & GENL_DONT_VALIDATE_DUMP) &&
-           nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx))
-               goto err;
+               if (nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx))
+                       goto err;
+       }
 
        nla_nest_end(skb, nest_op);
        nla_nest_end(skb, nest_pol);
@@ -1399,16 +1402,19 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
        void *hdr;
 
        if (!ctx->policies) {
+               struct genl_split_ops doit, dumpit;
                struct genl_ops op;
 
                if (ctx->single_op) {
-                       int err;
-
-                       err = genl_get_cmd(ctx->op, ctx->rt, &op);
-                       if (WARN_ON(err))
-                               return err;
+                       if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO,
+                                              ctx->rt, &doit) &&
+                           genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP,
+                                              ctx->rt, &dumpit)) {
+                               WARN_ON(1);
+                               return -ENOENT;
+                       }
 
-                       if (ctrl_dumppolicy_put_op(skb, cb, &op))
+                       if (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit))
                                return skb->len;
 
                        /* don't enter the loop below */
@@ -1418,7 +1424,12 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
                while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) {
                        genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op);
 
-                       if (ctrl_dumppolicy_put_op(skb, cb, &op))
+                       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 (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit))
                                return skb->len;
 
                        ctx->opidx++;