netfilter: nftables: avoid potential overflows on 32bit arches
User space could ask for very large hash tables, we need to make sure
our size computations wont overflow.
nf_tables_newset() needs to double check the u64 size
will fit into size_t field.
Fixes: 0ed6389c48
("netfilter: nf_tables: rename set implementations")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
a54754ec98
commit
6c8774a94e
|
@ -4184,6 +4184,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||||
unsigned char *udata;
|
unsigned char *udata;
|
||||||
struct nft_set *set;
|
struct nft_set *set;
|
||||||
struct nft_ctx ctx;
|
struct nft_ctx ctx;
|
||||||
|
size_t alloc_size;
|
||||||
u64 timeout;
|
u64 timeout;
|
||||||
char *name;
|
char *name;
|
||||||
int err, i;
|
int err, i;
|
||||||
|
@ -4329,8 +4330,10 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
|
||||||
size = 0;
|
size = 0;
|
||||||
if (ops->privsize != NULL)
|
if (ops->privsize != NULL)
|
||||||
size = ops->privsize(nla, &desc);
|
size = ops->privsize(nla, &desc);
|
||||||
|
alloc_size = sizeof(*set) + size + udlen;
|
||||||
set = kvzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
|
if (alloc_size < size)
|
||||||
|
return -ENOMEM;
|
||||||
|
set = kvzalloc(alloc_size, GFP_KERNEL);
|
||||||
if (!set)
|
if (!set)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -623,7 +623,7 @@ static u64 nft_hash_privsize(const struct nlattr * const nla[],
|
||||||
const struct nft_set_desc *desc)
|
const struct nft_set_desc *desc)
|
||||||
{
|
{
|
||||||
return sizeof(struct nft_hash) +
|
return sizeof(struct nft_hash) +
|
||||||
nft_hash_buckets(desc->size) * sizeof(struct hlist_head);
|
(u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nft_hash_init(const struct nft_set *set,
|
static int nft_hash_init(const struct nft_set *set,
|
||||||
|
@ -663,8 +663,8 @@ static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
est->size = sizeof(struct nft_hash) +
|
est->size = sizeof(struct nft_hash) +
|
||||||
nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
|
(u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
|
||||||
desc->size * sizeof(struct nft_hash_elem);
|
(u64)desc->size * sizeof(struct nft_hash_elem);
|
||||||
est->lookup = NFT_SET_CLASS_O_1;
|
est->lookup = NFT_SET_CLASS_O_1;
|
||||||
est->space = NFT_SET_CLASS_O_N;
|
est->space = NFT_SET_CLASS_O_N;
|
||||||
|
|
||||||
|
@ -681,8 +681,8 @@ static bool nft_hash_fast_estimate(const struct nft_set_desc *desc, u32 features
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
est->size = sizeof(struct nft_hash) +
|
est->size = sizeof(struct nft_hash) +
|
||||||
nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
|
(u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
|
||||||
desc->size * sizeof(struct nft_hash_elem);
|
(u64)desc->size * sizeof(struct nft_hash_elem);
|
||||||
est->lookup = NFT_SET_CLASS_O_1;
|
est->lookup = NFT_SET_CLASS_O_1;
|
||||||
est->space = NFT_SET_CLASS_O_N;
|
est->space = NFT_SET_CLASS_O_N;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue