Commit 212e7f56 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct

An earlier commit (1b789577,
"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: add67461 ("netfilter: add struct net * to target parameters")
Reported-by: syzbot+91bdd8eece0f6629ec8b@syzkaller.appspotmail.com
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent c1209593
...@@ -496,12 +496,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, ...@@ -496,12 +496,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
return 0; 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_tgdtor_param par;
struct xt_entry_target *t; struct xt_entry_target *t;
t = arpt_get_target(e); t = arpt_get_target(e);
par.net = net;
par.target = t->u.kernel.target; par.target = t->u.kernel.target;
par.targinfo = t->data; par.targinfo = t->data;
par.family = NFPROTO_ARP; par.family = NFPROTO_ARP;
...@@ -584,7 +585,7 @@ static int translate_table(struct net *net, ...@@ -584,7 +585,7 @@ static int translate_table(struct net *net,
xt_entry_foreach(iter, entry0, newinfo->size) { xt_entry_foreach(iter, entry0, newinfo->size) {
if (i-- == 0) if (i-- == 0)
break; break;
cleanup_entry(iter); cleanup_entry(iter, net);
} }
return ret; return ret;
} }
...@@ -927,7 +928,7 @@ static int __do_replace(struct net *net, const char *name, ...@@ -927,7 +928,7 @@ static int __do_replace(struct net *net, const char *name,
/* Decrease module usage counts and free resource */ /* Decrease module usage counts and free resource */
loc_cpu_old_entry = oldinfo->entries; loc_cpu_old_entry = oldinfo->entries;
xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
cleanup_entry(iter); cleanup_entry(iter, net);
xt_free_table_info(oldinfo); xt_free_table_info(oldinfo);
if (copy_to_user(counters_ptr, counters, if (copy_to_user(counters_ptr, counters,
...@@ -990,7 +991,7 @@ static int do_replace(struct net *net, const void __user *user, ...@@ -990,7 +991,7 @@ static int do_replace(struct net *net, const void __user *user,
free_newinfo_untrans: free_newinfo_untrans:
xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
cleanup_entry(iter); cleanup_entry(iter, net);
free_newinfo: free_newinfo:
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
return ret; return ret;
...@@ -1287,7 +1288,7 @@ static int compat_do_replace(struct net *net, void __user *user, ...@@ -1287,7 +1288,7 @@ static int compat_do_replace(struct net *net, void __user *user,
free_newinfo_untrans: free_newinfo_untrans:
xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
cleanup_entry(iter); cleanup_entry(iter, net);
free_newinfo: free_newinfo:
xt_free_table_info(newinfo); xt_free_table_info(newinfo);
return ret; return ret;
...@@ -1514,7 +1515,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len ...@@ -1514,7 +1515,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
return ret; return ret;
} }
static void __arpt_unregister_table(struct xt_table *table) static void __arpt_unregister_table(struct net *net, struct xt_table *table)
{ {
struct xt_table_info *private; struct xt_table_info *private;
void *loc_cpu_entry; void *loc_cpu_entry;
...@@ -1526,7 +1527,7 @@ static void __arpt_unregister_table(struct xt_table *table) ...@@ -1526,7 +1527,7 @@ static void __arpt_unregister_table(struct xt_table *table)
/* Decrease module usage counts and free resources */ /* Decrease module usage counts and free resources */
loc_cpu_entry = private->entries; loc_cpu_entry = private->entries;
xt_entry_foreach(iter, loc_cpu_entry, private->size) xt_entry_foreach(iter, loc_cpu_entry, private->size)
cleanup_entry(iter); cleanup_entry(iter, net);
if (private->number > private->initial_entries) if (private->number > private->initial_entries)
module_put(table_owner); module_put(table_owner);
xt_free_table_info(private); xt_free_table_info(private);
...@@ -1566,7 +1567,7 @@ int arpt_register_table(struct net *net, ...@@ -1566,7 +1567,7 @@ int arpt_register_table(struct net *net,
ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks)); ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
if (ret != 0) { if (ret != 0) {
__arpt_unregister_table(new_table); __arpt_unregister_table(net, new_table);
*res = NULL; *res = NULL;
} }
...@@ -1581,7 +1582,7 @@ void arpt_unregister_table(struct net *net, struct xt_table *table, ...@@ -1581,7 +1582,7 @@ void arpt_unregister_table(struct net *net, struct xt_table *table,
const struct nf_hook_ops *ops) const struct nf_hook_ops *ops)
{ {
nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
__arpt_unregister_table(table); __arpt_unregister_table(net, table);
} }
/* The built-in targets: standard (NULL) and error. */ /* The built-in targets: standard (NULL) and error. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment