]> git.hungrycats.org Git - linux/commitdiff
netfilter: nf_tables: extended netlink error reporting for netdevice
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 20 Apr 2023 22:34:28 +0000 (00:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 May 2023 11:58:56 +0000 (13:58 +0200)
[ Upstream commit c3c060adc0249355411a93e61888051e6902b8a1 ]

Flowtable and netdev chains are bound to one or several netdevice,
extend netlink error reporting to specify the the netdevice that
triggers the error.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 8509f62b0b07 ("netfilter: nf_tables: hit ENOENT on unexisting chain/flowtable update with missing attributes")
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/netfilter/nf_tables_api.c

index 96bc4b8ded4236cba47a70ca668c569d602afb8c..4b0a84a39b19e4609da0ce3fa7308d712bba3303 100644 (file)
@@ -1951,7 +1951,8 @@ static struct nft_hook *nft_hook_list_find(struct list_head *hook_list,
 
 static int nf_tables_parse_netdev_hooks(struct net *net,
                                        const struct nlattr *attr,
-                                       struct list_head *hook_list)
+                                       struct list_head *hook_list,
+                                       struct netlink_ext_ack *extack)
 {
        struct nft_hook *hook, *next;
        const struct nlattr *tmp;
@@ -1965,10 +1966,12 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
 
                hook = nft_netdev_hook_alloc(net, tmp);
                if (IS_ERR(hook)) {
+                       NL_SET_BAD_ATTR(extack, tmp);
                        err = PTR_ERR(hook);
                        goto err_hook;
                }
                if (nft_hook_list_find(hook_list, hook)) {
+                       NL_SET_BAD_ATTR(extack, tmp);
                        kfree(hook);
                        err = -EEXIST;
                        goto err_hook;
@@ -2001,20 +2004,23 @@ struct nft_chain_hook {
 
 static int nft_chain_parse_netdev(struct net *net,
                                  struct nlattr *tb[],
-                                 struct list_head *hook_list)
+                                 struct list_head *hook_list,
+                                 struct netlink_ext_ack *extack)
 {
        struct nft_hook *hook;
        int err;
 
        if (tb[NFTA_HOOK_DEV]) {
                hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV]);
-               if (IS_ERR(hook))
+               if (IS_ERR(hook)) {
+                       NL_SET_BAD_ATTR(extack, tb[NFTA_HOOK_DEV]);
                        return PTR_ERR(hook);
+               }
 
                list_add_tail(&hook->list, hook_list);
        } else if (tb[NFTA_HOOK_DEVS]) {
                err = nf_tables_parse_netdev_hooks(net, tb[NFTA_HOOK_DEVS],
-                                                  hook_list);
+                                                  hook_list, extack);
                if (err < 0)
                        return err;
 
@@ -2082,7 +2088,7 @@ static int nft_chain_parse_hook(struct net *net,
 
        INIT_LIST_HEAD(&hook->list);
        if (nft_base_chain_netdev(family, hook->num)) {
-               err = nft_chain_parse_netdev(net, ha, &hook->list);
+               err = nft_chain_parse_netdev(net, ha, &hook->list, extack);
                if (err < 0) {
                        module_put(type->owner);
                        return err;
@@ -7552,7 +7558,8 @@ static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX
 static int nft_flowtable_parse_hook(const struct nft_ctx *ctx,
                                    const struct nlattr *attr,
                                    struct nft_flowtable_hook *flowtable_hook,
-                                   struct nft_flowtable *flowtable, bool add)
+                                   struct nft_flowtable *flowtable,
+                                   struct netlink_ext_ack *extack, bool add)
 {
        struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1];
        struct nft_hook *hook;
@@ -7599,7 +7606,8 @@ static int nft_flowtable_parse_hook(const struct nft_ctx *ctx,
        if (tb[NFTA_FLOWTABLE_HOOK_DEVS]) {
                err = nf_tables_parse_netdev_hooks(ctx->net,
                                                   tb[NFTA_FLOWTABLE_HOOK_DEVS],
-                                                  &flowtable_hook->list);
+                                                  &flowtable_hook->list,
+                                                  extack);
                if (err < 0)
                        return err;
        }
@@ -7742,7 +7750,8 @@ static void nft_flowtable_hooks_destroy(struct list_head *hook_list)
 }
 
 static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
-                               struct nft_flowtable *flowtable)
+                               struct nft_flowtable *flowtable,
+                               struct netlink_ext_ack *extack)
 {
        const struct nlattr * const *nla = ctx->nla;
        struct nft_flowtable_hook flowtable_hook;
@@ -7753,7 +7762,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
        int err;
 
        err = nft_flowtable_parse_hook(ctx, nla[NFTA_FLOWTABLE_HOOK],
-                                      &flowtable_hook, flowtable, false);
+                                      &flowtable_hook, flowtable, extack, false);
        if (err < 0)
                return err;
 
@@ -7858,7 +7867,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
 
                nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
 
-               return nft_flowtable_update(&ctx, info->nlh, flowtable);
+               return nft_flowtable_update(&ctx, info->nlh, flowtable, extack);
        }
 
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
@@ -7899,7 +7908,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
                goto err3;
 
        err = nft_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
-                                      &flowtable_hook, flowtable, true);
+                                      &flowtable_hook, flowtable, extack, true);
        if (err < 0)
                goto err4;
 
@@ -7951,7 +7960,8 @@ static void nft_flowtable_hook_release(struct nft_flowtable_hook *flowtable_hook
 }
 
 static int nft_delflowtable_hook(struct nft_ctx *ctx,
-                                struct nft_flowtable *flowtable)
+                                struct nft_flowtable *flowtable,
+                                struct netlink_ext_ack *extack)
 {
        const struct nlattr * const *nla = ctx->nla;
        struct nft_flowtable_hook flowtable_hook;
@@ -7961,7 +7971,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
        int err;
 
        err = nft_flowtable_parse_hook(ctx, nla[NFTA_FLOWTABLE_HOOK],
-                                      &flowtable_hook, flowtable, false);
+                                      &flowtable_hook, flowtable, extack, false);
        if (err < 0)
                return err;
 
@@ -8039,7 +8049,7 @@ static int nf_tables_delflowtable(struct sk_buff *skb,
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
 
        if (nla[NFTA_FLOWTABLE_HOOK])
-               return nft_delflowtable_hook(&ctx, flowtable);
+               return nft_delflowtable_hook(&ctx, flowtable, extack);
 
        if (flowtable->use > 0) {
                NL_SET_BAD_ATTR(extack, attr);