]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
iptables-nft: exit nonzero when iptables-save cannot decode all expressions
authorFlorian Westphal <fw@strlen.de>
Wed, 23 Nov 2022 13:44:22 +0000 (14:44 +0100)
committerFlorian Westphal <fw@strlen.de>
Wed, 23 Nov 2022 14:05:12 +0000 (15:05 +0100)
We always return 0, even if we printed some error message half-way.
Increment an error counter whenever an error message was printed so that
the chain-loop can exit with an error if this counter is nonzero.

Another effect is that iptables-save will no longer print the COMMIT line anmore.

Reported-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Phil Sutter <phil@nwl.cc>
iptables/nft-bridge.c
iptables/nft-shared.c
iptables/nft-shared.h
iptables/nft.c
iptables/nft.h

index e8ac7a364169b12c5942aa8235811a9d378429a8..4367d072906df612243317e2b8396301c7c23ced 100644 (file)
@@ -563,12 +563,12 @@ static void nft_bridge_parse_target(struct xtables_target *t,
        cs->jumpto = t->name;
 }
 
-static void nft_rule_to_ebtables_command_state(struct nft_handle *h,
+static bool nft_rule_to_ebtables_command_state(struct nft_handle *h,
                                               const struct nftnl_rule *r,
                                               struct iptables_command_state *cs)
 {
        cs->eb.bitmask = EBT_NOPROTO;
-       nft_rule_to_iptables_command_state(h, r, cs);
+       return nft_rule_to_iptables_command_state(h, r, cs);
 }
 
 static void print_iface(const char *option, const char *name, bool invert)
index 97512e3f43ffe940649bad325346bfd94cee2779..63d251986f65b1236d414fd900bff948aa4f88be 100644 (file)
@@ -1199,7 +1199,7 @@ static void nft_parse_range(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
        }
 }
 
-void nft_rule_to_iptables_command_state(struct nft_handle *h,
+bool nft_rule_to_iptables_command_state(struct nft_handle *h,
                                        const struct nftnl_rule *r,
                                        struct iptables_command_state *cs)
 {
@@ -1210,10 +1210,11 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
                .h = h,
                .table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE),
        };
+       bool ret = true;
 
        iter = nftnl_expr_iter_create(r);
        if (iter == NULL)
-               return;
+               return false;
 
        ctx.iter = iter;
        expr = nftnl_expr_iter_next(iter);
@@ -1249,6 +1250,7 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
                if (ctx.errmsg) {
                        fprintf(stderr, "%s", ctx.errmsg);
                        ctx.errmsg = NULL;
+                       ret = false;
                }
 
                expr = nftnl_expr_iter_next(iter);
@@ -1270,7 +1272,7 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
                        match = xtables_find_match("comment", XTF_TRY_LOAD,
                                                   &cs->matches);
                        if (match == NULL)
-                               return;
+                               return false;
 
                        size = XT_ALIGN(sizeof(struct xt_entry_match))
                                + match->size;
@@ -1287,6 +1289,8 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
 
        if (!cs->jumpto)
                cs->jumpto = "";
+
+       return ret;
 }
 
 void nft_clear_iptables_command_state(struct iptables_command_state *cs)
index 3d935d5324b01ffb7300e6432e0fbe4786387375..e2c3ac7b0cc5c084f22bc16a5cb406d1e1ec39ea 100644 (file)
@@ -159,7 +159,7 @@ struct nft_family_ops {
        void (*parse_target)(struct xtables_target *t,
                             struct iptables_command_state *cs);
        void (*init_cs)(struct iptables_command_state *cs);
-       void (*rule_to_cs)(struct nft_handle *h, const struct nftnl_rule *r,
+       bool (*rule_to_cs)(struct nft_handle *h, const struct nftnl_rule *r,
                           struct iptables_command_state *cs);
        void (*clear_cs)(struct iptables_command_state *cs);
        int (*xlate)(const struct iptables_command_state *cs,
@@ -213,7 +213,7 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
               unsigned char *outiface_mask, uint8_t *invflags);
 void __get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, uint8_t *op);
 void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv);
-void nft_rule_to_iptables_command_state(struct nft_handle *h,
+bool nft_rule_to_iptables_command_state(struct nft_handle *h,
                                        const struct nftnl_rule *r,
                                        struct iptables_command_state *cs);
 void nft_clear_iptables_command_state(struct iptables_command_state *cs);
index 4c0110bb80401568d1cb29aa121f102d083442a2..67c5877ce9ccf8f99ad7d2aef9f29999fd43607f 100644 (file)
@@ -1748,15 +1748,16 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
        return 1;
 }
 
-void
+bool
 nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
                    enum nft_rule_print type, unsigned int format)
 {
        const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
        struct iptables_command_state cs = {};
        struct nft_family_ops *ops = h->ops;
+       bool ret;
 
-       ops->rule_to_cs(h, r, &cs);
+       ret = ops->rule_to_cs(h, r, &cs);
 
        if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)))
                printf("[%llu:%llu] ", (unsigned long long)cs.counters.pcnt,
@@ -1777,6 +1778,8 @@ nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
 
        if (ops->clear_cs)
                ops->clear_cs(&cs);
+
+       return ret;
 }
 
 static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
@@ -1887,6 +1890,7 @@ int nft_chain_save(struct nft_chain *nc, void *data)
 struct nft_rule_save_data {
        struct nft_handle *h;
        unsigned int format;
+       unsigned int errors;
 };
 
 static int nft_rule_save_cb(struct nft_chain *c, void *data)
@@ -1901,7 +1905,11 @@ static int nft_rule_save_cb(struct nft_chain *c, void *data)
 
        r = nftnl_rule_iter_next(iter);
        while (r != NULL) {
-               nft_rule_print_save(d->h, r, NFT_RULE_APPEND, d->format);
+               bool ret = nft_rule_print_save(d->h, r, NFT_RULE_APPEND, d->format);
+
+               if (!ret)
+                       d->errors++;
+
                r = nftnl_rule_iter_next(iter);
        }
 
@@ -1919,6 +1927,9 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
 
        ret = nft_chain_foreach(h, table, nft_rule_save_cb, &d);
 
+       if (ret == 0 && d.errors)
+               xtables_error(VERSION_PROBLEM, "Cannot decode all rules provided by kernel");
+
        /* the core expects 1 for success and 0 for error */
        return ret == 0 ? 1 : 0;
 }
@@ -2341,15 +2352,18 @@ static bool nft_rule_cmp(struct nft_handle *h, struct nftnl_rule *r,
                         struct nftnl_rule *rule)
 {
        struct iptables_command_state _cs = {}, this = {}, *cs = &_cs;
-       bool ret = false;
+       bool ret = false, ret_this, ret_that;
 
-       h->ops->rule_to_cs(h, r, &this);
-       h->ops->rule_to_cs(h, rule, cs);
+       ret_this = h->ops->rule_to_cs(h, r, &this);
+       ret_that = h->ops->rule_to_cs(h, rule, cs);
 
        DEBUGP("comparing with... ");
 #ifdef DEBUG_DEL
        nft_rule_print_save(h, r, NFT_RULE_APPEND, 0);
 #endif
+       if (!ret_this || !ret_that)
+               DEBUGP("Cannot convert rules: %d %d\n", ret_this, ret_that);
+
        if (!h->ops->is_same(cs, &this))
                goto out;
 
index 68b0910c8e1827eef8289ff3f95761832ac12b4c..caff1fdeff92e7462624e81ce454317a53eecb01 100644 (file)
@@ -203,7 +203,7 @@ enum nft_rule_print {
        NFT_RULE_DEL,
 };
 
-void nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
+bool nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
                         enum nft_rule_print type, unsigned int format);
 
 uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);