From: Pablo Neira Ayuso pablo@netfilter.org
stable inclusion from stable-v4.19.317 commit 40188a25a9847dbeb7ec67517174a835a677752f category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ CVE: CVE-2024-42070
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 7931d32955e09d0a11b1fe0b6aac1bfa061c005c ]
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 Signed-off-by: Sasha Levin sashal@kernel.org
Conflicts: include/net/netfilter/nf_tables.h net/netfilter/nft_lookup.c [nf_tables.h conflicts due to context, nft_lookup.c conflicts because e1c59f90e1a6 ("netfilter: nftables: add nft_parse_register_store() and use it") is not merged.] Signed-off-by: Wang Hai wanghai38@huawei.com --- include/net/netfilter/nf_tables.h | 5 +++++ net/netfilter/nf_tables_api.c | 8 ++++---- net/netfilter/nft_lookup.c | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index ecc301ee1556..247e4637b458 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -438,6 +438,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 struct nft_set *nft_set_container_of(const void *priv) { return (void *)priv - offsetof(struct nft_set, data); diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 97e56cadb4bf..133cff3a3f77 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3961,8 +3961,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_EXPR) && @@ -7174,6 +7173,9 @@ 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) @@ -7182,8 +7184,6 @@ int nft_validate_register_store(const struct nft_ctx *ctx, FIELD_SIZEOF(struct nft_regs, data)) return -ERANGE;
- if (data != NULL && type != NFT_DATA_VALUE) - return -EINVAL; return 0; } } diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index cb9e937a5ce0..0d7a21ec9b11 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -102,7 +102,7 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]); err = nft_validate_register_store(ctx, priv->dreg, NULL, - set->dtype, set->dlen); + nft_set_datatype(set), set->dlen); if (err < 0) return err; } else if (set->flags & NFT_SET_MAP)