Skip to content

Commit

Permalink
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data …
Browse files Browse the repository at this point in the history
…registers

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: 9651851 ("netfilter: add nftables")
Reported-by: Linus Torvalds <[email protected]>
Signed-off-by: Pablo Neira Ayuso <[email protected]>
  • Loading branch information
ummakynes committed Jun 26, 2024
1 parent aef5daa commit 7931d32
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 5 deletions.
5 changes: 5 additions & 0 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) &&
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
}
Expand Down
3 changes: 2 additions & 1 deletion net/netfilter/nft_lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 7931d32

Please sign in to comment.