Skip to content

Commit 80eec78

Browse files
ummakynessmb49
authored andcommitted
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
BugLink: https://bugs.launchpad.net/bugs/2076435 [ Upstream commit 7931d32 ] 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 <torvalds@linuxfoundation.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Portia Stephens <portia.stephens@canonical.com> Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
1 parent 67704fd commit 80eec78

File tree

3 files changed

+11
-5
lines changed

3 files changed

+11
-5
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,11 @@ static inline void *nft_set_priv(const struct nft_set *set)
619619
return (void *)set->data;
620620
}
621621

622+
static inline enum nft_data_types nft_set_datatype(const struct nft_set *set)
623+
{
624+
return set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
625+
}
626+
622627
static inline bool nft_set_gc_is_pending(const struct nft_set *s)
623628
{
624629
return refcount_read(&s->refs) != 1;

net/netfilter/nf_tables_api.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5736,8 +5736,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
57365736

57375737
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
57385738
nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext),
5739-
set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE,
5740-
set->dlen) < 0)
5739+
nft_set_datatype(set), set->dlen) < 0)
57415740
goto nla_put_failure;
57425741

57435742
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS) &&
@@ -11061,6 +11060,9 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
1106111060

1106211061
return 0;
1106311062
default:
11063+
if (type != NFT_DATA_VALUE)
11064+
return -EINVAL;
11065+
1106411066
if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
1106511067
return -EINVAL;
1106611068
if (len == 0)
@@ -11069,8 +11071,6 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
1106911071
sizeof_field(struct nft_regs, data))
1107011072
return -ERANGE;
1107111073

11072-
if (data != NULL && type != NFT_DATA_VALUE)
11073-
return -EINVAL;
1107411074
return 0;
1107511075
}
1107611076
}

net/netfilter/nft_lookup.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
132132
return -EINVAL;
133133

134134
err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
135-
&priv->dreg, NULL, set->dtype,
135+
&priv->dreg, NULL,
136+
nft_set_datatype(set),
136137
set->dlen);
137138
if (err < 0)
138139
return err;

0 commit comments

Comments
 (0)