aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-02-12 14:13:43 -0500
committerDavid S. Miller <davem@davemloft.net>2007-02-12 14:13:43 -0500
commitc0e912d7ed8999f87fa7f084928aac1266e251f3 (patch)
treeec48a83001871b4e0db78ee9eab520a1fbb02e14 /net
parentabbaccda4c364815b8b1a82c45a94f60760e13e1 (diff)
[NETFILTER]: nf_conntrack: fix invalid conntrack statistics RCU assumption
NF_CT_STAT_INC assumes rcu_read_lock in nf_hook_slow disables preemption as well, making it legal to use __get_cpu_var without disabling preemption manually. The assumption is not correct anymore with preemptable RCU, additionally we need to protect against softirqs when not holding nf_conntrack_lock. Add NF_CT_STAT_INC_ATOMIC macro, which disables local softirqs, and use where necessary. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c14
2 files changed, 9 insertions, 9 deletions
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index a2353edf4ebc..4b7be4bb4d03 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -154,8 +154,8 @@ ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
154 */ 154 */
155 if ((protoff < 0) || (protoff > (*pskb)->len)) { 155 if ((protoff < 0) || (protoff > (*pskb)->len)) {
156 DEBUGP("ip6_conntrack_core: can't find proto in pkt\n"); 156 DEBUGP("ip6_conntrack_core: can't find proto in pkt\n");
157 NF_CT_STAT_INC(error); 157 NF_CT_STAT_INC_ATOMIC(error);
158 NF_CT_STAT_INC(invalid); 158 NF_CT_STAT_INC_ATOMIC(invalid);
159 return -NF_ACCEPT; 159 return -NF_ACCEPT;
160 } 160 }
161 161
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3deeb900263b..d59640e2377b 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -563,7 +563,7 @@ static int early_drop(struct list_head *chain)
563 if (del_timer(&ct->timeout)) { 563 if (del_timer(&ct->timeout)) {
564 death_by_timeout((unsigned long)ct); 564 death_by_timeout((unsigned long)ct);
565 dropped = 1; 565 dropped = 1;
566 NF_CT_STAT_INC(early_drop); 566 NF_CT_STAT_INC_ATOMIC(early_drop);
567 } 567 }
568 nf_ct_put(ct); 568 nf_ct_put(ct);
569 return dropped; 569 return dropped;
@@ -821,7 +821,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
821 821
822 /* Previously seen (loopback or untracked)? Ignore. */ 822 /* Previously seen (loopback or untracked)? Ignore. */
823 if ((*pskb)->nfct) { 823 if ((*pskb)->nfct) {
824 NF_CT_STAT_INC(ignore); 824 NF_CT_STAT_INC_ATOMIC(ignore);
825 return NF_ACCEPT; 825 return NF_ACCEPT;
826 } 826 }
827 827
@@ -840,8 +840,8 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
840 * core what to do with the packet. */ 840 * core what to do with the packet. */
841 if (l4proto->error != NULL && 841 if (l4proto->error != NULL &&
842 (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) { 842 (ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
843 NF_CT_STAT_INC(error); 843 NF_CT_STAT_INC_ATOMIC(error);
844 NF_CT_STAT_INC(invalid); 844 NF_CT_STAT_INC_ATOMIC(invalid);
845 return -ret; 845 return -ret;
846 } 846 }
847 847
@@ -849,13 +849,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
849 &set_reply, &ctinfo); 849 &set_reply, &ctinfo);
850 if (!ct) { 850 if (!ct) {
851 /* Not valid part of a connection */ 851 /* Not valid part of a connection */
852 NF_CT_STAT_INC(invalid); 852 NF_CT_STAT_INC_ATOMIC(invalid);
853 return NF_ACCEPT; 853 return NF_ACCEPT;
854 } 854 }
855 855
856 if (IS_ERR(ct)) { 856 if (IS_ERR(ct)) {
857 /* Too stressed to deal. */ 857 /* Too stressed to deal. */
858 NF_CT_STAT_INC(drop); 858 NF_CT_STAT_INC_ATOMIC(drop);
859 return NF_DROP; 859 return NF_DROP;
860 } 860 }
861 861
@@ -868,7 +868,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
868 DEBUGP("nf_conntrack_in: Can't track with proto module\n"); 868 DEBUGP("nf_conntrack_in: Can't track with proto module\n");
869 nf_conntrack_put((*pskb)->nfct); 869 nf_conntrack_put((*pskb)->nfct);
870 (*pskb)->nfct = NULL; 870 (*pskb)->nfct = NULL;
871 NF_CT_STAT_INC(invalid); 871 NF_CT_STAT_INC_ATOMIC(invalid);
872 return -ret; 872 return -ret;
873 } 873 }
874 874