netfilter: nf_tables: disallow jump to implicit chain from set element
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 8 Aug 2022 17:30:07 +0000 (19:30 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Tue, 9 Aug 2022 18:13:29 +0000 (20:13 +0200)
Extend struct nft_data_desc to add a flag field that specifies
nft_data_init() is being called for set element data.

Use it to disallow jump to implicit chain from set element, only jump
to chain via immediate expression is allowed.

Fixes: d0e2c7de92c7 ("netfilter: nf_tables: add NFT_CHAIN_BINDING")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c

index 1554f1e7215bb0ead6a026463e5cd4e13a433941..99aae36c04b97532bc6884497db8ad6482fdfdcc 100644 (file)
@@ -221,10 +221,15 @@ struct nft_ctx {
        bool                            report;
 };
 
+enum nft_data_desc_flags {
+       NFT_DATA_DESC_SETELEM   = (1 << 0),
+};
+
 struct nft_data_desc {
        enum nft_data_types             type;
        unsigned int                    size;
        unsigned int                    len;
+       unsigned int                    flags;
 };
 
 int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data,
index 05896765c68f1a32e68ac56ddeb49bc831b11325..460b0925ea603cfce5cc6ea16bf3eb8ab5bbe3a1 100644 (file)
@@ -5226,6 +5226,7 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
        desc->type = dtype;
        desc->size = NFT_DATA_VALUE_MAXLEN;
        desc->len = set->dlen;
+       desc->flags = NFT_DATA_DESC_SETELEM;
 
        return nft_data_init(ctx, data, desc, attr);
 }
@@ -9665,6 +9666,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
                        return PTR_ERR(chain);
                if (nft_is_base_chain(chain))
                        return -EOPNOTSUPP;
+               if (desc->flags & NFT_DATA_DESC_SETELEM &&
+                   chain->flags & NFT_CHAIN_BINDING)
+                       return -EINVAL;
 
                chain->use++;
                data->verdict.chain = chain;