netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 6 Dec 2019 21:09:14 +0000 (22:09 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 12 Jan 2020 11:17:09 +0000 (12:17 +0100)
[ Upstream commit 0d2c96af797ba149e559c5875c0151384ab6dd14 ]

Userspace might bogusly sent NFT_DATA_VERDICT in several netlink
attributes that assume NFT_DATA_VALUE. Moreover, make sure that error
path invokes nft_data_release() to decrement the reference count on the
chain object.

Fixes: 96518518cc41 ("netfilter: add nftables")
Fixes: 0f3cd9b36977 ("netfilter: nf_tables: add range expression")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/netfilter/nf_tables_api.c
net/netfilter/nft_bitwise.c
net/netfilter/nft_cmp.c
net/netfilter/nft_range.c

index 42f79f9..4711a8b 100644 (file)
@@ -4117,8 +4117,10 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                return err;
 
        err = -EINVAL;
-       if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
+       if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
+               nft_data_release(&elem.key.val, desc.type);
                return err;
+       }
 
        priv = set->ops->get(ctx->net, set, &elem, flags);
        if (IS_ERR(priv))
index fff8073..058ee84 100644 (file)
@@ -83,7 +83,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
                            tb[NFTA_BITWISE_MASK]);
        if (err < 0)
                return err;
-       if (d1.len != priv->len) {
+       if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
                err = -EINVAL;
                goto err1;
        }
@@ -92,7 +92,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
                            tb[NFTA_BITWISE_XOR]);
        if (err < 0)
                goto err1;
-       if (d2.len != priv->len) {
+       if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
                err = -EINVAL;
                goto err2;
        }
index 79d48c1..7007045 100644 (file)
@@ -82,6 +82,12 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        if (err < 0)
                return err;
 
+       if (desc.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               nft_data_release(&priv->data, desc.type);
+               return err;
+       }
+
        priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
        err = nft_validate_register_load(priv->sreg, desc.len);
        if (err < 0)
index cedb96c..2e1d2ec 100644 (file)
@@ -70,11 +70,21 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        if (err < 0)
                return err;
 
+       if (desc_from.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               goto err1;
+       }
+
        err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to),
                            &desc_to, tb[NFTA_RANGE_TO_DATA]);
        if (err < 0)
                goto err1;
 
+       if (desc_to.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               goto err2;
+       }
+
        if (desc_from.len != desc_to.len) {
                err = -EINVAL;
                goto err2;