diff options
author | Patrick McHardy <kaber@trash.net> | 2006-11-29 02:35:25 +0100 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-02 21:31:22 -0800 |
commit | 337fbc4166967a72c3cc71c597bdde7e6a8633ab (patch) | |
tree | 95b2d47e55db3991f66090525b7e28455a6ca39b /net/ipv4/netfilter/ip_conntrack_sip.c | |
parent | 468ec44bd5a863736d955f78b8c38896f26864a1 (diff) | |
download | linux-337fbc4166967a72c3cc71c597bdde7e6a8633ab.tar.gz |
[NETFILTER]: ip_conntrack: fix NAT helper unload races
The NAT helpr hooks are protected by RCU, but all of the
conntrack helpers test and use the global pointers instead
of copying them first using rcu_dereference()
Also replace synchronize_net() by synchronize_rcu() for clarity
since sychronizing only with packet receive processing is
insufficient to prevent races.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4/netfilter/ip_conntrack_sip.c')
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_sip.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index f4f75995a9e4c..bf423db4ed466 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -308,6 +308,7 @@ static int set_expected_rtp(struct sk_buff **pskb, struct ip_conntrack_expect *exp; enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); int ret; + typeof(ip_nat_sdp_hook) ip_nat_sdp; exp = ip_conntrack_expect_alloc(ct); if (exp == NULL) @@ -328,8 +329,9 @@ static int set_expected_rtp(struct sk_buff **pskb, exp->expectfn = NULL; exp->flags = 0; - if (ip_nat_sdp_hook) - ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr); + ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook); + if (ip_nat_sdp) + ret = ip_nat_sdp(pskb, ctinfo, exp, dptr); else { if (ip_conntrack_expect_related(exp) != 0) ret = NF_DROP; @@ -351,6 +353,7 @@ static int sip_help(struct sk_buff **pskb, int matchoff, matchlen; __be32 ipaddr; u_int16_t port; + typeof(ip_nat_sip_hook) ip_nat_sip; /* No Data ? */ dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); @@ -368,8 +371,9 @@ static int sip_help(struct sk_buff **pskb, goto out; } - if (ip_nat_sip_hook) { - if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) { + ip_nat_sip = rcu_dereference(ip_nat_sip_hook); + if (ip_nat_sip) { + if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) { ret = NF_DROP; goto out; } |