]> www.infradead.org Git - users/hch/configfs.git/commitdiff
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 26 Jun 2024 21:15:38 +0000 (23:15 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 26 Jun 2024 23:09:51 +0000 (01:09 +0200)
register store validation for NFT_DATA_VALUE is conditional, however,
the datatype is always either NFT_DATA_VALUE or NFT_DATA_VERDICT. This
only requires a new helper function to infer the register type from the
set datatype so this conditional check can be removed. Otherwise,
pointer to chain object can be leaked through the registers.

Fixes: 96518518cc41 ("netfilter: add nftables")
Reported-by: Linus Torvalds <torvalds@linuxfoundation.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_lookup.c

index 2796153b03dad3213ad9c52d3c90c5846cfdb771..188d41da1a40af6e37ac13be42b3d90c8f2c4eb5 100644 (file)
@@ -619,6 +619,11 @@ static inline void *nft_set_priv(const struct nft_set *set)
        return (void *)set->data;
 }
 
+static inline enum nft_data_types nft_set_datatype(const struct nft_set *set)
+{
+       return set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
+}
+
 static inline bool nft_set_gc_is_pending(const struct nft_set *s)
 {
        return refcount_read(&s->refs) != 1;
index be3b4c90d2eda11bc9218e38e5c97f5b2ecb4034..e8dcf41d360d9bef6aff2752cfd00080c92aed47 100644 (file)
@@ -5740,8 +5740,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
 
        if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
            nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext),
-                         set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE,
-                         set->dlen) < 0)
+                         nft_set_datatype(set), set->dlen) < 0)
                goto nla_put_failure;
 
        if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS) &&
@@ -11073,6 +11072,9 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
 
                return 0;
        default:
+               if (type != NFT_DATA_VALUE)
+                       return -EINVAL;
+
                if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
                        return -EINVAL;
                if (len == 0)
@@ -11081,8 +11083,6 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
                    sizeof_field(struct nft_regs, data))
                        return -ERANGE;
 
-               if (data != NULL && type != NFT_DATA_VALUE)
-                       return -EINVAL;
                return 0;
        }
 }
index b314ca728a2912da717995840ef3dc337eace815..f3080fa1b22631b9e6adbcb26bdb36b1eb8b6cf4 100644 (file)
@@ -132,7 +132,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
                        return -EINVAL;
 
                err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
-                                              &priv->dreg, NULL, set->dtype,
+                                              &priv->dreg, NULL,
+                                              nft_set_datatype(set),
                                               set->dlen);
                if (err < 0)
                        return err;