From 642d628b2c92e5283bbd3c849c7099c64ab68856 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 12 Feb 2007 11:12:40 -0800 Subject: [NETFILTER]: ip_conntrack: properly use RCU API for ip_ct_protos array Replace preempt_{enable,disable} based RCU by proper use of the RCU API and add missing rcu_read_lock/rcu_read_unlock calls in all paths not obviously only used within packet process context (nfnetlink_conntrack). Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'net/ipv4/netfilter/ip_conntrack_core.c') diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 508e6007a19..e7de6d31b85 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -318,9 +318,11 @@ destroy_conntrack(struct nf_conntrack *nfct) /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to ip_conntrack_lock!!! -HW */ + rcu_read_lock(); proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum); if (proto && proto->destroy) proto->destroy(ct); + rcu_read_unlock(); if (ip_conntrack_destroyed) ip_conntrack_destroyed(ct); @@ -595,13 +597,13 @@ ip_conntrack_proto_find_get(u_int8_t protocol) { struct ip_conntrack_protocol *p; - preempt_disable(); + rcu_read_lock(); p = __ip_conntrack_proto_find(protocol); if (p) { if (!try_module_get(p->me)) p = &ip_conntrack_generic_protocol; } - preempt_enable(); + rcu_read_unlock(); return p; } @@ -830,6 +832,7 @@ unsigned int ip_conntrack_in(unsigned int hooknum, } #endif + /* rcu_read_lock()ed by nf_hook_slow */ proto = __ip_conntrack_proto_find((*pskb)->nh.iph->protocol); /* It may be an special packet, error, unclean... @@ -875,8 +878,15 @@ unsigned int ip_conntrack_in(unsigned int hooknum, int invert_tuplepr(struct ip_conntrack_tuple *inverse, const struct ip_conntrack_tuple *orig) { - return ip_ct_invert_tuple(inverse, orig, - __ip_conntrack_proto_find(orig->dst.protonum)); + struct ip_conntrack_protocol *proto; + int ret; + + rcu_read_lock(); + proto = __ip_conntrack_proto_find(orig->dst.protonum); + ret = ip_ct_invert_tuple(inverse, orig, proto); + rcu_read_unlock(); + + return ret; } /* Would two expected things clash? */ @@ -1507,11 +1517,11 @@ int __init ip_conntrack_init(void) /* Don't NEED lock here, but good form anyway. */ write_lock_bh(&ip_conntrack_lock); for (i = 0; i < MAX_IP_CT_PROTO; i++) - ip_ct_protos[i] = &ip_conntrack_generic_protocol; + rcu_assign_pointer(ip_ct_protos[i], &ip_conntrack_generic_protocol); /* Sew in builtin protocols. */ - ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp; - ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp; - ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp; + rcu_assign_pointer(ip_ct_protos[IPPROTO_TCP], &ip_conntrack_protocol_tcp); + rcu_assign_pointer(ip_ct_protos[IPPROTO_UDP], &ip_conntrack_protocol_udp); + rcu_assign_pointer(ip_ct_protos[IPPROTO_ICMP], &ip_conntrack_protocol_icmp); write_unlock_bh(&ip_conntrack_lock); /* For use by ipt_REJECT */ -- cgit v1.2.3