diff options
author | Alexander Duyck | 2015-03-04 15:04:46 -0800 |
---|---|---|
committer | David S. Miller | 2015-03-04 23:35:18 -0500 |
commit | 1de3d87bcd2c2e631500b9e4f0c40b38ce0d0d57 (patch) | |
tree | 9c5454c691c99de935aab3699cf85cf97151a68b /net | |
parent | 71e8b67d0fdd2fe22a657bb98716c5cf0e31e828 (diff) |
fib_trie: Prevent allocating tnode if bits is too big for size_t
This patch adds code to prevent us from attempting to allocate a tnode with
a size larger than what can be represented by size_t.
Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/fib_trie.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 08676c56efc3..fae34ad4bb1a 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -277,6 +277,8 @@ static inline void alias_free_mem_rcu(struct fib_alias *fa) #define TNODE_KMALLOC_MAX \ ilog2((PAGE_SIZE - TNODE_SIZE(0)) / sizeof(struct tnode *)) +#define TNODE_VMALLOC_MAX \ + ilog2((SIZE_MAX - TNODE_SIZE(0)) / sizeof(struct tnode *)) static void __node_free_rcu(struct rcu_head *head) { @@ -292,8 +294,17 @@ static void __node_free_rcu(struct rcu_head *head) #define node_free(n) call_rcu(&n->rcu, __node_free_rcu) -static struct tnode *tnode_alloc(size_t size) +static struct tnode *tnode_alloc(int bits) { + size_t size; + + /* verify bits is within bounds */ + if (bits > TNODE_VMALLOC_MAX) + return NULL; + + /* determine size and verify it is non-zero and didn't overflow */ + size = TNODE_SIZE(1ul << bits); + if (size <= PAGE_SIZE) return kzalloc(size, GFP_KERNEL); else @@ -334,8 +345,7 @@ static struct tnode *leaf_new(t_key key, struct fib_alias *fa) static struct tnode *tnode_new(t_key key, int pos, int bits) { - size_t sz = TNODE_SIZE(1ul << bits); - struct tnode *tn = tnode_alloc(sz); + struct tnode *tn = tnode_alloc(bits); unsigned int shift = pos + bits; /* verify bits and pos their msb bits clear and values are valid */ |