xt_hashlimit: allocate a copy of name explicitly, don't rely on procfs guts
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 19 Apr 2013 10:43:33 +0000 (06:43 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 29 Apr 2013 19:41:49 +0000 (15:41 -0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
net/netfilter/xt_hashlimit.c

index ebfad037b11f2fc0e420117d631f2a2e2b66f88f..905c328ed5a821873ebcc24f85c6d778015f0502 100644 (file)
@@ -107,6 +107,7 @@ struct xt_hashlimit_htable {
 
        /* seq_file stuff */
        struct proc_dir_entry *pde;
+       const char *name;
        struct net *net;
 
        struct hlist_head hash[0];      /* hashtable itself */
@@ -253,6 +254,11 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
        hinfo->count = 0;
        hinfo->family = family;
        hinfo->rnd_initialized = false;
+       hinfo->name = kstrdup(minfo->name, GFP_KERNEL);
+       if (!hinfo->name) {
+               vfree(hinfo);
+               return -ENOMEM;
+       }
        spin_lock_init(&hinfo->lock);
 
        hinfo->pde = proc_create_data(minfo->name, 0,
@@ -260,6 +266,7 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
                hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
                &dl_file_ops, hinfo);
        if (hinfo->pde == NULL) {
+               kfree(hinfo->name);
                vfree(hinfo);
                return -ENOMEM;
        }
@@ -330,9 +337,10 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo)
                parent = hashlimit_net->ip6t_hashlimit;
 
        if(parent != NULL)
-               remove_proc_entry(hinfo->pde->name, parent);
+               remove_proc_entry(hinfo->name, parent);
 
        htable_selective_cleanup(hinfo, select_all);
+       kfree(hinfo->name);
        vfree(hinfo);
 }
 
@@ -344,7 +352,7 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
        struct xt_hashlimit_htable *hinfo;
 
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) {
-               if (!strcmp(name, hinfo->pde->name) &&
+               if (!strcmp(name, hinfo->name) &&
                    hinfo->family == family) {
                        hinfo->use++;
                        return hinfo;
@@ -887,7 +895,7 @@ static void __net_exit hashlimit_proc_net_exit(struct net *net)
                pde = hashlimit_net->ip6t_hashlimit;
 
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node)
-               remove_proc_entry(hinfo->pde->name, pde);
+               remove_proc_entry(hinfo->name, pde);
 
        hashlimit_net->ipt_hashlimit = NULL;
        hashlimit_net->ip6t_hashlimit = NULL;