summaryrefslogtreecommitdiffstats
path: root/net-Fix-iptables-get_counters.patch
blob: 28b7b4dd91547a4e74ff119bceebe9dc41281ca5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
From 3c408972097c1dba92c8213bb6127ba92bf2f50d Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Tue, 27 Apr 2010 10:05:28 +0200
Subject: [PATCH] net: Fix iptables get_counters()

commit 863c3ad87b10617464fc52c21fc7e31987910559 in tip.

The preempt-rt changes to iptables get_counters() left the counters
array uninitialized which results in random packet statistic numbers.

Reported-by: prd.gtt@operamail.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 net/ipv4/netfilter/ip_tables.c  |    9 +++++----
 net/ipv6/netfilter/ip6_tables.c |   10 +++++-----
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 1c33431..5f6042e 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -906,7 +906,7 @@ get_counters(const struct xt_table_info *t,
 	struct ipt_entry *iter;
 	unsigned int cpu;
 	unsigned int i;
-	unsigned int curcpu = NR_CPUS;
+	unsigned int curcpu;
 
 	/* Instead of clearing (by a previous call to memset())
 	 * the counters and using adds, we set the counters
@@ -916,16 +916,17 @@ get_counters(const struct xt_table_info *t,
 	 * if new softirq were to run and call ipt_do_table
 	 */
 	local_bh_disable();
-#ifndef CONFIG_PREEMPT_RT
-	curcpu = smp_processor_id();
+	curcpu = raw_smp_processor_id();
 
 	i = 0;
+	xt_info_wrlock(curcpu);
 	xt_entry_foreach(iter, t->entries[curcpu], t->size) {
 		SET_COUNTER(counters[i], iter->counters.bcnt,
 			    iter->counters.pcnt);
 		++i;
 	}
-#endif
+	xt_info_wrunlock(curcpu);
+
 	for_each_possible_cpu(cpu) {
 		if (cpu == curcpu)
 			continue;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6d5b78b..ff7ce7b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -936,7 +936,7 @@ get_counters(const struct xt_table_info *t,
 	struct ip6t_entry *iter;
 	unsigned int cpu;
 	unsigned int i;
-	unsigned int curcpu = NR_CPUS;
+	unsigned int curcpu;
 
 	/* Instead of clearing (by a previous call to memset())
 	 * the counters and using adds, we set the counters
@@ -946,17 +946,17 @@ get_counters(const struct xt_table_info *t,
 	 * if new softirq were to run and call ipt_do_table
 	 */
 	local_bh_disable();
-
-#ifndef CONFIG_PREEMPT_RT
-	curcpu = smp_processor_id();
+	curcpu = raw_smp_processor_id();
 
 	i = 0;
+	xt_info_wrlock(curcpu);
 	xt_entry_foreach(iter, t->entries[curcpu], t->size) {
 		SET_COUNTER(counters[i], iter->counters.bcnt,
 			    iter->counters.pcnt);
 		++i;
 	}
-#endif
+	xt_info_wrunlock(curcpu);
+
 	for_each_possible_cpu(cpu) {
 		if (cpu == curcpu)
 			continue;
-- 
1.7.0.4