Merge tag 'nfsd-4.6-1' of git://linux-nfs.org/~bfields/linux
[deliverable/linux.git] / net / netfilter / x_tables.c
index c8a0b7da5ff4607ee6d8f163e9677cae1505a976..582c9cfd6567ce4c7d5b3f86c15732b33a63e1b4 100644 (file)
@@ -659,6 +659,9 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
        struct xt_table_info *info = NULL;
        size_t sz = sizeof(*info) + size;
 
+       if (sz < sizeof(*info))
+               return NULL;
+
        /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
        if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
                return NULL;
@@ -694,12 +697,45 @@ EXPORT_SYMBOL(xt_free_table_info);
 struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
                                    const char *name)
 {
-       struct xt_table *t;
+       struct xt_table *t, *found = NULL;
 
        mutex_lock(&xt[af].mutex);
        list_for_each_entry(t, &net->xt.tables[af], list)
                if (strcmp(t->name, name) == 0 && try_module_get(t->me))
                        return t;
+
+       if (net == &init_net)
+               goto out;
+
+       /* Table doesn't exist in this netns, re-try init */
+       list_for_each_entry(t, &init_net.xt.tables[af], list) {
+               if (strcmp(t->name, name))
+                       continue;
+               if (!try_module_get(t->me))
+                       return NULL;
+
+               mutex_unlock(&xt[af].mutex);
+               if (t->table_init(net) != 0) {
+                       module_put(t->me);
+                       return NULL;
+               }
+
+               found = t;
+
+               mutex_lock(&xt[af].mutex);
+               break;
+       }
+
+       if (!found)
+               goto out;
+
+       /* and once again: */
+       list_for_each_entry(t, &net->xt.tables[af], list)
+               if (strcmp(t->name, name) == 0)
+                       return t;
+
+       module_put(found->me);
+ out:
        mutex_unlock(&xt[af].mutex);
        return NULL;
 }
@@ -1170,20 +1206,20 @@ static const struct file_operations xt_target_ops = {
 #endif /* CONFIG_PROC_FS */
 
 /**
- * xt_hook_link - set up hooks for a new table
+ * xt_hook_ops_alloc - set up hooks for a new table
  * @table:     table with metadata needed to set up hooks
  * @fn:                Hook function
  *
- * This function will take care of creating and registering the necessary
- * Netfilter hooks for XT tables.
+ * This function will create the nf_hook_ops that the x_table needs
+ * to hand to xt_hook_link_net().
  */
-struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
+struct nf_hook_ops *
+xt_hook_ops_alloc(const struct xt_table *table, nf_hookfn *fn)
 {
        unsigned int hook_mask = table->valid_hooks;
        uint8_t i, num_hooks = hweight32(hook_mask);
        uint8_t hooknum;
        struct nf_hook_ops *ops;
-       int ret;
 
        ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
        if (ops == NULL)
@@ -1200,27 +1236,9 @@ struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
                ++i;
        }
 
-       ret = nf_register_hooks(ops, num_hooks);
-       if (ret < 0) {
-               kfree(ops);
-               return ERR_PTR(ret);
-       }
-
        return ops;
 }
-EXPORT_SYMBOL_GPL(xt_hook_link);
-
-/**
- * xt_hook_unlink - remove hooks for a table
- * @ops:       nf_hook_ops array as returned by nf_hook_link
- * @hook_mask: the very same mask that was passed to nf_hook_link
- */
-void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
-{
-       nf_unregister_hooks(ops, hweight32(table->valid_hooks));
-       kfree(ops);
-}
-EXPORT_SYMBOL_GPL(xt_hook_unlink);
+EXPORT_SYMBOL_GPL(xt_hook_ops_alloc);
 
 int xt_proto_init(struct net *net, u_int8_t af)
 {
This page took 0.038453 seconds and 5 git commands to generate.