netfilter: return -EFAULT directly when counters_ptr is NULL
Subsystems (3)
PATCH 1/1 netfilter: return -EFAULT directly when counters_ptr is NULL
Now if the copy_to_user() fail, __do_replace just silent error, because new table is alread replaced. But at the beginning of __do_replace(), if we notice that user supply no memory to store counters, we should not replace table, so we can just returen -EFAULT directly.
--- net/bridge/netfilter/ebtables.c | 3 +++ net/ipv4/netfilter/arp_tables.c | 4 ++++ net/ipv4/netfilter/ip_tables.c | 4 ++++ net/ipv6/netfilter/ip6_tables.c | 4 ++++ 4 files changed, 15 insertions(+)
net/bridge/netfilter/ebtables.c +3 -0
@@ -983,6 +983,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,struct ebt_table_info *table;struct ebt_table *t; +if (!repl->counters) +return -EFAULT ; +/* the user wants counters back the check on the size is done later, when we have the lock */ if (repl->num_counters) {
net/ipv4/netfilter/arp_tables.c +4 -0
@@ -999,6 +999,10 @@ static int __do_replace(struct net *net, const char *name,struct arpt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;
net/ipv4/netfilter/ip_tables.c +4 -0
@@ -1186,6 +1186,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ipt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;
net/ipv6/netfilter/ip6_tables.c +4 -0
@@ -1196,6 +1196,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ip6t_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;
Signature · 1 line
1.8.3.1
Pablo Neira Ayuso
maintainerQuoted 5 lines · Duan Jiong
Now if the
copy_to_user()fail,__do_replacejust silent error, because new table is alread replaced. But at the beginning of__do_replace(), if we notice that user supply no memory to store counters, we should not replace table, so we can just returen-EFAULTdirectly.
This is independent of the change you mention, right?
I mean, userspace can send us null counters and we'll crash.
Another nitpick comment below:
Quoted 27 lines
Signed-off-by Duan Jiong <[email protected]>--- net/bridge/netfilter/ebtables.c | 3 +++ net/ipv4/netfilter/arp_tables.c | 4 ++++ net/ipv4/netfilter/ip_tables.c | 4 ++++ net/ipv6/netfilter/ip6_tables.c | 4 ++++ 4 files changed, 15 insertions(+)net/bridge/netfilter/ebtables.c +3
-0@@ -983,6 +983,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,struct ebt_table_info *table;struct ebt_table *t; +if (!repl->counters) +return -EFAULT ; +/* the user wants counters back the check on the size is done later, when we have the lock */ if (repl->num_counters) {net/ipv4/netfilter/arp_tables.c +0
-0
net/ipv4/netfilter/arp_tables.c static int __do_replace(struct net *net, const char *name, · line 1005
Quoted 7 lines
net/ipv4/netfilter/arp_tables.c +4
-0@@ -999,6 +999,10 @@ static int __do_replace(struct net *net, const char *name,struct arpt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + }
Please move this check before 'ret = 0'. So we avoid the unnecessary initialization. Same thing below.
Quoted 35 lines
net/ipv4/netfilter/arp_tables.c +0
-0counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;net/ipv4/netfilter/ip_tables.c +4
-0@@ -1186,6 +1186,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ipt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;net/ipv6/netfilter/ip6_tables.c +4
-0@@ -1196,6 +1196,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ip6t_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;Signature · 1 line
1.8.3.1
Quoted 10 lines · Pablo Neira Ayuso
Quoted 5 lines · Duan Jiong
Now if the
copy_to_user()fail,__do_replacejust silent error, because new table is alread replaced. But at the beginning of__do_replace(), if we notice that user supply no memory to store counters, we should not replace table, so we can just returen-EFAULTdirectly.This is independent of the change you mention, right?
I mean, userspace can send us null counters and we'll crash.
I have tested it, and it will not cause crash.
The goal here is to avoid mallocing memory to store counter and replacing table when userspace send us null counters.
Thanks,
Duan
Quoted 78 lines
Another nitpick comment below:
Quoted 27 lines
Signed-off-by Duan Jiong <[email protected]>--- net/bridge/netfilter/ebtables.c | 3 +++ net/ipv4/netfilter/arp_tables.c | 4 ++++ net/ipv4/netfilter/ip_tables.c | 4 ++++ net/ipv6/netfilter/ip6_tables.c | 4 ++++ 4 files changed, 15 insertions(+)net/bridge/netfilter/ebtables.c +3
-0@@ -983,6 +983,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,struct ebt_table_info *table;struct ebt_table *t; +if (!repl->counters) +return -EFAULT ; +/* the user wants counters back the check on the size is done later, when we have the lock */ if (repl->num_counters) {net/ipv4/netfilter/arp_tables.c +0
-0net/ipv4/netfilter/arp_tables.c static int __do_replace(struct net *net, const char *name, · line 1005
Quoted 7 lines
net/ipv4/netfilter/arp_tables.c +4
-0@@ -999,6 +999,10 @@ static int __do_replace(struct net *net, const char *name,struct arpt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + }Please move this check before 'ret = 0'. So we avoid the unnecessary initialization. Same thing below.
Quoted 35 lines
net/ipv4/netfilter/arp_tables.c +0
-0counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;net/ipv4/netfilter/ip_tables.c +4
-0@@ -1186,6 +1186,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ipt_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;net/ipv6/netfilter/ip6_tables.c +4
-0@@ -1196,6 +1196,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,struct ip6t_entry *iter; ret =0 ; +if (!counters_ptr) { + ret = -EFAULT ; + goto out; + } counters =vzalloc (num_counters *sizeof (struct xt_counters ));if (!counters) { ret = -ENOMEM ;Signature · 1 line
1.8.3.1.