netfilter: nf_tables: allow large allocations for new sets
authorPablo Neira Ayuso <pablo@netfilter.org>
Mon, 22 May 2017 16:47:59 +0000 (17:47 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 29 May 2017 10:46:20 +0000 (12:46 +0200)
The new fixed size hashtable backend implementation may result in a
large array of buckets that would spew splats from mm. Update this code
to fall back on vmalloc in case the memory allocation order is too
costly.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_api.c

index 2969016..bc8f03a 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/list.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <linux/vmalloc.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nf_tables.h>
@@ -3054,10 +3055,11 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
        if (ops->privsize != NULL)
                size = ops->privsize(nla, &desc);
 
-       err = -ENOMEM;
-       set = kzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
-       if (set == NULL)
+       set = kvzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
+       if (!set) {
+               err = -ENOMEM;
                goto err1;
+       }
 
        nla_strlcpy(name, nla[NFTA_SET_NAME], sizeof(set->name));
        err = nf_tables_set_alloc_name(&ctx, set, name);
@@ -3100,7 +3102,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
 err3:
        ops->destroy(set);
 err2:
-       kfree(set);
+       kvfree(set);
 err1:
        module_put(ops->type->owner);
        return err;
@@ -3110,7 +3112,7 @@ static void nft_set_destroy(struct nft_set *set)
 {
        set->ops->destroy(set);
        module_put(set->ops->type->owner);
-       kfree(set);
+       kvfree(set);
 }
 
 static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)