netfilter: nftables: extend error reporting for chain updates
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 12 Oct 2020 14:54:30 +0000 (16:54 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 12 Oct 2020 14:54:30 +0000 (16:54 +0200)
The initial support for netlink extended ACK is missing the chain update
path, which results in misleading error reporting in case of EEXIST.

Fixes 36dd1bcc07e5 ("netfilter: nf_tables: initial support for extended ACK reporting")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_api.c

index 4603b667973a53a5188150e7aa88bd521fde9f7a..0e43063767d65dc35123b5544e2d48838093717b 100644 (file)
@@ -2103,7 +2103,8 @@ static bool nft_hook_list_equal(struct list_head *hook_list1,
 }
 
 static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
-                             u32 flags)
+                             u32 flags, const struct nlattr *attr,
+                             struct netlink_ext_ack *extack)
 {
        const struct nlattr * const *nla = ctx->nla;
        struct nft_table *table = ctx->table;
@@ -2119,9 +2120,10 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                return -EOPNOTSUPP;
 
        if (nla[NFTA_CHAIN_HOOK]) {
-               if (!nft_is_base_chain(chain))
+               if (!nft_is_base_chain(chain)) {
+                       NL_SET_BAD_ATTR(extack, attr);
                        return -EEXIST;
-
+               }
                err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
                                           false);
                if (err < 0)
@@ -2130,6 +2132,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                basechain = nft_base_chain(chain);
                if (basechain->type != hook.type) {
                        nft_chain_release_hook(&hook);
+                       NL_SET_BAD_ATTR(extack, attr);
                        return -EEXIST;
                }
 
@@ -2137,6 +2140,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                        if (!nft_hook_list_equal(&basechain->hook_list,
                                                 &hook.list)) {
                                nft_chain_release_hook(&hook);
+                               NL_SET_BAD_ATTR(extack, attr);
                                return -EEXIST;
                        }
                } else {
@@ -2144,6 +2148,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                        if (ops->hooknum != hook.num ||
                            ops->priority != hook.priority) {
                                nft_chain_release_hook(&hook);
+                               NL_SET_BAD_ATTR(extack, attr);
                                return -EEXIST;
                        }
                }
@@ -2156,8 +2161,10 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
 
                chain2 = nft_chain_lookup(ctx->net, table,
                                          nla[NFTA_CHAIN_NAME], genmask);
-               if (!IS_ERR(chain2))
+               if (!IS_ERR(chain2)) {
+                       NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
                        return -EEXIST;
+               }
        }
 
        if (nla[NFTA_CHAIN_COUNTERS]) {
@@ -2200,6 +2207,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                            nft_trans_chain_update(tmp) &&
                            nft_trans_chain_name(tmp) &&
                            strcmp(name, nft_trans_chain_name(tmp)) == 0) {
+                               NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
                                kfree(name);
                                goto err;
                        }
@@ -2322,7 +2330,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
                        return -EOPNOTSUPP;
 
                flags |= chain->flags & NFT_CHAIN_BASE;
-               return nf_tables_updchain(&ctx, genmask, policy, flags);
+               return nf_tables_updchain(&ctx, genmask, policy, flags, attr,
+                                         extack);
        }
 
        return nf_tables_addchain(&ctx, family, genmask, policy, flags);