]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct
authorFlorian Westphal <fw@strlen.de>
Sat, 11 Jan 2020 22:19:53 +0000 (23:19 +0100)
committerBen Hutchings <ben@decadent.org.uk>
Tue, 28 Apr 2020 18:03:25 +0000 (19:03 +0100)
commit 212e7f56605ef9688d0846db60c6c6ec06544095 upstream.

An earlier commit (1b789577f655060d98d20e,
"netfilter: arp_tables: init netns pointer in xt_tgchk_param struct")
fixed missing net initialization for arptables, but turns out it was
incomplete.  We can get a very similar struct net NULL deref during
error unwinding:

general protection fault: 0000 [#1] PREEMPT SMP KASAN
RIP: 0010:xt_rateest_put+0xa1/0x440 net/netfilter/xt_RATEEST.c:77
 xt_rateest_tg_destroy+0x72/0xa0 net/netfilter/xt_RATEEST.c:175
 cleanup_entry net/ipv4/netfilter/arp_tables.c:509 [inline]
 translate_table+0x11f4/0x1d80 net/ipv4/netfilter/arp_tables.c:587
 do_replace net/ipv4/netfilter/arp_tables.c:981 [inline]
 do_arpt_set_ctl+0x317/0x650 net/ipv4/netfilter/arp_tables.c:1461

Also init the netns pointer in xt_tgdtor_param struct.

Fixes: add67461240c1d ("netfilter: add struct net * to target parameters")
Reported-by: syzbot+91bdd8eece0f6629ec8b@syzkaller.appspotmail.com
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
[bwh: Backported to 3.16:
 - __arpt_unregister_table() has not been split out of
   arpt_unregister_table()
 - Add "net" parameter to arpt_unregister_table() and update its only
   caller in arptable_filter.c]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
include/linux/netfilter_arp/arp_tables.h
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/arptable_filter.c

index cfb7191e6efa55633dfa8eb52855e6248ccb3d4f..f817d18664289c4279f869546046b2b2fc628a3f 100644 (file)
@@ -51,7 +51,7 @@ extern void *arpt_alloc_initial_table(const struct xt_table *);
 extern struct xt_table *arpt_register_table(struct net *net,
                                            const struct xt_table *table,
                                            const struct arpt_replace *repl);
-extern void arpt_unregister_table(struct xt_table *table);
+extern void arpt_unregister_table(struct net *, struct xt_table *table);
 extern unsigned int arpt_do_table(struct sk_buff *skb,
                                  unsigned int hook,
                                  const struct net_device *in,
index f5359a530859aa2db1b58bf8ed10bf88bcdda5ba..d491af8a11be57f605257a1638cfe8fae825801d 100644 (file)
@@ -602,12 +602,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
        return 0;
 }
 
-static inline void cleanup_entry(struct arpt_entry *e)
+static void cleanup_entry(struct arpt_entry *e, struct net *net)
 {
        struct xt_tgdtor_param par;
        struct xt_entry_target *t;
 
        t = arpt_get_target(e);
+       par.net      = net;
        par.target   = t->u.kernel.target;
        par.targinfo = t->data;
        par.family   = NFPROTO_ARP;
@@ -706,7 +707,7 @@ static int translate_table(struct net *net,
                xt_entry_foreach(iter, entry0, newinfo->size) {
                        if (i-- == 0)
                                break;
-                       cleanup_entry(iter);
+                       cleanup_entry(iter, net);
                }
                return ret;
        }
@@ -1051,7 +1052,7 @@ static int __do_replace(struct net *net, const char *name,
        /* Decrease module usage counts and free resource */
        loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
        xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
 
        xt_free_table_info(oldinfo);
        if (copy_to_user(counters_ptr, counters,
@@ -1118,7 +1119,7 @@ static int do_replace(struct net *net, const void __user *user,
 
  free_newinfo_untrans:
        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
  free_newinfo:
        xt_free_table_info(newinfo);
        return ret;
@@ -1431,7 +1432,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 
  free_newinfo_untrans:
        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
  free_newinfo:
        xt_free_table_info(newinfo);
        return ret;
@@ -1708,7 +1709,7 @@ out:
        return ERR_PTR(ret);
 }
 
-void arpt_unregister_table(struct xt_table *table)
+void arpt_unregister_table(struct net *net, struct xt_table *table)
 {
        struct xt_table_info *private;
        void *loc_cpu_entry;
@@ -1720,7 +1721,7 @@ void arpt_unregister_table(struct xt_table *table)
        /* Decrease module usage counts and free resources */
        loc_cpu_entry = private->entries[raw_smp_processor_id()];
        xt_entry_foreach(iter, loc_cpu_entry, private->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
        if (private->number > private->initial_entries)
                module_put(table_owner);
        xt_free_table_info(private);
index 802ddecb30b8110474da0e0a34c134aceaece43b..5375fb03d26ba01d19ed41038dbde71df771226e 100644 (file)
@@ -54,7 +54,7 @@ static int __net_init arptable_filter_net_init(struct net *net)
 
 static void __net_exit arptable_filter_net_exit(struct net *net)
 {
-       arpt_unregister_table(net->ipv4.arptable_filter);
+       arpt_unregister_table(net, net->ipv4.arptable_filter);
 }
 
 static struct pernet_operations arptable_filter_net_ops = {