Some functions are called by nf_hook() and these
functions hold rcu_read_lock() But nf_hook() already holds
rcu_read_lock() therefore callee's rcu_read_lock() are useless.
Below messages are calltrace.

1. ip_vs_in_stats
-ip_vs_leave
--ip_{tcp, udp, sctp}_conn_schedule
---ip_vs_protocol.conn_schedule
----ip_vs_try_to_schedule
-----ip_vs_in_icmp
------ip_vs_in
-------ip_vs_remote_request4
--------nf_hook_ops.hook
---------nf_hook()
-------ip_vs_local_request4
--------nf_hook_ops.hook
---------nf_hook()
-------ip_vs_remote_request6
--------nf_hook_ops.hook
---------nf_hook()
-------ip_vs_local_request6
--------nf_hook_ops.hook
---------nf_hook()
------ip_vs_forward_icmp
--------nf_hook_ops.hook
---------nf_hook()
-----ip_vs_in_icmp_v6
------ip_vs_in
-------nf_hook()
------ip_vs_forward_icmp_v6
-------nf_hook_ops.hook
--------nf_hook()
-----ip_vs_in
------nf_hook()
-ip_vs_in_icmp
--nf_hook()
-ip_vs_in_icmp_v6
--nf_hook()
-ip_vs_in
--nf_hook()

2.ip_vs_out_stats
-handle_response_icmp
--ip_vs_out_icmp
---ip_vs_out
----ip_vs_reply4
-----nf_hook_ops.hook
------nf_hook()
----ip_vs_local_reply4
-----nf_hook_ops.hook
------nf_hook()
----ip_vs_reply6
-----nf_hook_ops.hook
------nf_hook()
----ip_vs_local_reply6
-----nf_hook_ops.hook
------nf_hook()
--ip_vs_out_icmp_v6
---ip_vs_out
----nf_hook()
-handle_response
--ip_vs_out
---nf_hook()
-ip_vs_in_icmp
--nf_hook()

3.__ip_vs_rs_conn_out
-ip_vs_out
--nf_hook()

4.ip_vs_in_icmp
-nf_hook()

5.ip_vs_has_real_service
-ip_vs_out
--nf_hook()

6.ip_vs_ftp_out
-ip_vs_app.pkt_out
--app_tcp_pkt_out
---ip_vs_app_pkt_out
----{tcp, udp, sctp}_snat_handler
-----ip_vs_protocol.snat_handler
------handle_response
-------ip_vs_out
--------nf_hook()
--ip_vs_app_pkt_out
---nf_hook()

7.{tcp, udp, sctp}_conn_schedule
-nf_hook()

8. ip_vs_icmp_xmit
-ip_vs_in_icmp
--nf_hook()

9. ip_vs_icmp_xmit_v6
-ip_vs_in_icmp_v6
--nf_hook()

10. nf_conntrack_broadcast_help
-snmp_conntrack_help
--nf_conntrack_helper.help
---nf_hook()
-netbios_ns_help
--nf_conntrack_helper.help
---nf_hook()

11. pptp_expectfn
-exp_gre
--nf_conntrack_expect.expectfn
---init_conntrack
----nf_hook()

12. set_expected_rtp_rtcp
-process_sdp
--process_invite_response
---sip_handler.response
----process_sip_response
-----process_sip_msg
------sip_help_{tcp, udp}
-----nf_conntrack_helper.help
------nf_hook()
--process_update_response
---sip_handler.response
----process_sip_response
-----process_sip_msg
------sip_help_{tcp, udp}
-----nf_conntrack_helper.help
------nf_hook()
--process_prack_response
---sip_handler.response
----process_sip_response
-----process_sip_msg
------sip_help_{tcp, udp}
-----nf_conntrack_helper.help
------nf_hook()
--process_invite_request
---sip_handler.response
----process_sip_response
-----process_sip_msg
------sip_help_{tcp, udp}
-----nf_conntrack_helper.help
------nf_hook()
--sip_handler.request
---process_sip_request
----process_sip_msg
----sip_help_{tcp, udp}
-----nf_conntrack_helper.help
------nf_hook()

13. ctnl_timeout_find_get
-nf_ct_timeout_find_get_hook

14. tcpmss_reverse_mtu
-tcpmss_mangle_packet
--tcpmss_tg{4, 6}
---xt_target.target
----nf_hook()

15. tproxy_laddr4
-tproxy_tg4
--tproxy_tg4_{v0, v1}
---xt_target.target
----nf_hook()

16. match_lookup_rt6
-match_type6
--addrtype_mt6
---addrtype_mt_v1
---xt_match.match
----nf_hook()

17. check_hlist
-count_tree
--count_them
---connlimit_mt
---xt_match.match
----nf_hook()

18. hashlimit_mt_common
-hashlimit_mt_v1
--xt_match.match
---nf_hook()
-hashlimit_mt
--xt_match.match
---nf_hook()

19. xt_osf_match_packet
-xt_match.match
--nf_hook()

Signed-off-by: Taehee Yoo <[email protected]>
---
 net/netfilter/ipvs/ip_vs_core.c        | 12 ++++--------
 net/netfilter/ipvs/ip_vs_ctl.c         |  4 +---
 net/netfilter/ipvs/ip_vs_ftp.c         |  4 ++--
 net/netfilter/ipvs/ip_vs_proto_sctp.c  |  5 +----
 net/netfilter/ipvs/ip_vs_proto_tcp.c   |  6 +-----
 net/netfilter/ipvs/ip_vs_proto_udp.c   |  5 +----
 net/netfilter/ipvs/ip_vs_xmit.c        |  8 ++------
 net/netfilter/nf_conntrack_broadcast.c |  3 +--
 net/netfilter/nf_conntrack_pptp.c      |  3 +--
 net/netfilter/nf_conntrack_sip.c       |  4 +---
 net/netfilter/nfnetlink_cttimeout.c    |  3 +--
 net/netfilter/xt_TCPMSS.c              |  3 +--
 net/netfilter/xt_TPROXY.c              |  3 +--
 net/netfilter/xt_addrtype.c            |  3 +--
 net/netfilter/xt_connlimit.c           |  3 ---
 net/netfilter/xt_hashlimit.c           |  9 +++++----
 net/netfilter/xt_osf.c                 |  3 +--
 17 files changed, 25 insertions(+), 56 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d2d7bdf..cc4ddb9 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -125,14 +125,13 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
                s->cnt.inbytes += skb->len;
                u64_stats_update_end(&s->syncp);
 
-               rcu_read_lock();
+               /* rcu_read_lock()ed by nf_hook */
                svc = rcu_dereference(dest->svc);
                s = this_cpu_ptr(svc->stats.cpustats);
                u64_stats_update_begin(&s->syncp);
                s->cnt.inpkts++;
                s->cnt.inbytes += skb->len;
                u64_stats_update_end(&s->syncp);
-               rcu_read_unlock();
 
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
                u64_stats_update_begin(&s->syncp);
@@ -159,14 +158,13 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff 
*skb)
                s->cnt.outbytes += skb->len;
                u64_stats_update_end(&s->syncp);
 
-               rcu_read_lock();
+               /* rcu_read_lock()ed by nf_hook */
                svc = rcu_dereference(dest->svc);
                s = this_cpu_ptr(svc->stats.cpustats);
                u64_stats_update_begin(&s->syncp);
                s->cnt.outpkts++;
                s->cnt.outbytes += skb->len;
                u64_stats_update_end(&s->syncp);
-               rcu_read_unlock();
 
                s = this_cpu_ptr(ipvs->tot_stats.cpustats);
                u64_stats_update_begin(&s->syncp);
@@ -1222,7 +1220,7 @@ static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned 
int hooknum,
        if (!pptr)
                return NULL;
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        dest = ip_vs_find_real_service(ipvs, af, iph->protocol,
                                       &iph->saddr, pptr[0]);
        if (dest) {
@@ -1237,7 +1235,6 @@ static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned 
int hooknum,
                                                  pptr[0], pptr[1]);
                }
        }
-       rcu_read_unlock();
 
        return cp;
 }
@@ -1680,11 +1677,10 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff 
*skb, int *related,
                        if (dest) {
                                struct ip_vs_dest_dst *dest_dst;
 
-                               rcu_read_lock();
+                               /* rcu_read_lock()ed by nf_hook */
                                dest_dst = rcu_dereference(dest->dest_dst);
                                if (dest_dst)
                                        mtu = dst_mtu(dest_dst->dst_cache);
-                               rcu_read_unlock();
                        }
                        if (mtu > 68 + sizeof(struct iphdr))
                                mtu -= sizeof(struct iphdr);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 668d964..de1d5c9 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -550,18 +550,16 @@ bool ip_vs_has_real_service(struct netns_ipvs *ipvs, int 
af, __u16 protocol,
        /* Check for "full" addressed entries */
        hash = ip_vs_rs_hashkey(af, daddr, dport);
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        hlist_for_each_entry_rcu(dest, &ipvs->rs_table[hash], d_list) {
                if (dest->port == dport &&
                    dest->af == af &&
                    ip_vs_addr_equal(af, &dest->addr, daddr) &&
                    (dest->protocol == protocol || dest->vfwmark)) {
                        /* HIT */
-                       rcu_read_unlock();
                        return true;
                }
        }
-       rcu_read_unlock();
 
        return false;
 }
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index fb780be..ea0702d 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -268,14 +268,14 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct 
ip_vs_conn *cp,
                         * Mangling can only fail under memory pressure,
                         * hopefully it will succeed on the retransmitted
                         * packet.
+                        *
+                        * rcu_read_lock()ed by nf_hook
                         */
-                       rcu_read_lock();
                        mangled = nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
                                                           iph->ihl * 4,
                                                           start - data,
                                                           end - start,
                                                           buf, buf_len);
-                       rcu_read_unlock();
                        if (mangled) {
                                ip_vs_nfct_expect_related(skb, ct, n_cp,
                                                          IPPROTO_TCP, 0, 0);
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c 
b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 56f8e4b..801b366 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -39,7 +39,7 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                return 0;
        }
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        if (likely(!ip_vs_iph_inverse(iph)))
                svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
                                         &iph->daddr, ports[1]);
@@ -54,7 +54,6 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                         * It seems that we are very loaded.
                         * We have to drop this packet :(
                         */
-                       rcu_read_unlock();
                        *verdict = NF_DROP;
                        return 0;
                }
@@ -68,11 +67,9 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                                *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else
                                *verdict = NF_DROP;
-                       rcu_read_unlock();
                        return 0;
                }
        }
-       rcu_read_unlock();
        /* NF_ACCEPT */
        return 1;
 }
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c 
b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index 12dc8d5..245513a 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -63,9 +63,8 @@ tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
        }
 
        /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
-       rcu_read_lock();
-
        if (likely(!ip_vs_iph_inverse(iph)))
+               /* rcu_read_lock()ed by nf_hook */
                svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
                                         &iph->daddr, ports[1]);
        else
@@ -80,7 +79,6 @@ tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                         * It seems that we are very loaded.
                         * We have to drop this packet :(
                         */
-                       rcu_read_unlock();
                        *verdict = NF_DROP;
                        return 0;
                }
@@ -95,11 +93,9 @@ tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                                *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else
                                *verdict = NF_DROP;
-                       rcu_read_unlock();
                        return 0;
                }
        }
-       rcu_read_unlock();
        /* NF_ACCEPT */
        return 1;
 }
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c 
b/net/netfilter/ipvs/ip_vs_proto_udp.c
index e494e9a..563b148 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -53,7 +53,7 @@ udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                return 0;
        }
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        if (likely(!ip_vs_iph_inverse(iph)))
                svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
                                         &iph->daddr, ports[1]);
@@ -69,7 +69,6 @@ udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                         * It seems that we are very loaded.
                         * We have to drop this packet :(
                         */
-                       rcu_read_unlock();
                        *verdict = NF_DROP;
                        return 0;
                }
@@ -84,11 +83,9 @@ udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct 
sk_buff *skb,
                                *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else
                                *verdict = NF_DROP;
-                       rcu_read_unlock();
                        return 0;
                }
        }
-       rcu_read_unlock();
        /* NF_ACCEPT */
        return 1;
 }
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 2eab1e0..56588a2 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -1322,7 +1322,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn 
*cp,
        rt_mode = (hooknum != NF_INET_FORWARD) ?
                  IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
                  IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, 
cp->daddr.ip, rt_mode,
                                   NULL, iph);
        if (local < 0)
@@ -1368,12 +1368,10 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn 
*cp,
        skb->ignore_df = 1;
 
        rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local);
-       rcu_read_unlock();
        goto out;
 
   tx_error:
        kfree_skb(skb);
-       rcu_read_unlock();
        rc = NF_STOLEN;
   out:
        LeaveFunction(10);
@@ -1414,7 +1412,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn 
*cp,
        rt_mode = (hooknum != NF_INET_FORWARD) ?
                  IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
                  IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest,
                                      &cp->daddr.in6, NULL, ipvsh, 0, rt_mode);
        if (local < 0)
@@ -1460,12 +1458,10 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct 
ip_vs_conn *cp,
        skb->ignore_df = 1;
 
        rc = ip_vs_nat_send_or_cont(NFPROTO_IPV6, skb, cp, local);
-       rcu_read_unlock();
        goto out;
 
 tx_error:
        kfree_skb(skb);
-       rcu_read_unlock();
        rc = NF_STOLEN;
 out:
        LeaveFunction(10);
diff --git a/net/netfilter/nf_conntrack_broadcast.c 
b/net/netfilter/nf_conntrack_broadcast.c
index 4e99cca..276fb27 100644
--- a/net/netfilter/nf_conntrack_broadcast.c
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -40,7 +40,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
        if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
                goto out;
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        in_dev = __in_dev_get_rcu(rt->dst.dev);
        if (in_dev != NULL) {
                for_primary_ifa(in_dev) {
@@ -50,7 +50,6 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
                        }
                } endfor_ifa(in_dev);
        }
-       rcu_read_unlock();
 
        if (mask == 0)
                goto out;
diff --git a/net/netfilter/nf_conntrack_pptp.c 
b/net/netfilter/nf_conntrack_pptp.c
index 6959e93..7041e1b 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -113,7 +113,7 @@ static void pptp_expectfn(struct nf_conn *ct,
        /* Can you see how rusty this code is, compared with the pre-2.6.11
         * one? That's what happened to my shiny newnat of 2002 ;( -HW */
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        nf_nat_pptp_expectfn = rcu_dereference(nf_nat_pptp_hook_expectfn);
        if (nf_nat_pptp_expectfn && ct->master->status & IPS_NAT_MASK)
                nf_nat_pptp_expectfn(ct, exp);
@@ -136,7 +136,6 @@ static void pptp_expectfn(struct nf_conn *ct,
                        pr_debug("not found\n");
                }
        }
-       rcu_read_unlock();
 }
 
 static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index d38af42..78687fc 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -884,7 +884,6 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
        tuple.dst.u3            = *daddr;
        tuple.dst.u.udp.port    = port;
 
-       rcu_read_lock();
        do {
                exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
 
@@ -911,6 +910,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
        rtcp_port = htons(base_port + 1);
 
        if (direct_rtp) {
+               /* rcu_read_lock()ed by nf_hook */
                hooks = rcu_dereference(nf_nat_sip_hooks);
                if (hooks &&
                    !hooks->sdp_port(skb, protoff, dataoff, dptr, datalen,
@@ -919,7 +919,6 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
        }
 
        if (skip_expect) {
-               rcu_read_unlock();
                return NF_ACCEPT;
        }
 
@@ -952,7 +951,6 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, 
unsigned int protoff,
 err2:
        nf_ct_expect_put(rtp_exp);
 err1:
-       rcu_read_unlock();
        return ret;
 }
 
diff --git a/net/netfilter/nfnetlink_cttimeout.c 
b/net/netfilter/nfnetlink_cttimeout.c
index a3e7bb5..87d751a 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -524,12 +524,12 @@ static int cttimeout_default_get(struct net *net, struct 
sock *ctnl,
 }
 
 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+/* rcu_read_lock()ed by caller */
 static struct ctnl_timeout *
 ctnl_timeout_find_get(struct net *net, const char *name)
 {
        struct ctnl_timeout *timeout, *matching = NULL;
 
-       rcu_read_lock();
        list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
                if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
                        continue;
@@ -545,7 +545,6 @@ ctnl_timeout_find_get(struct net *net, const char *name)
                break;
        }
 err:
-       rcu_read_unlock();
        return matching;
 }
 
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index c64aca6..9dc155f 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -62,11 +62,10 @@ static u_int32_t tcpmss_reverse_mtu(struct net *net,
                memset(fl6, 0, sizeof(*fl6));
                fl6->daddr = ipv6_hdr(skb)->saddr;
        }
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        ai = nf_get_afinfo(family);
        if (ai != NULL)
                ai->route(net, (struct dst_entry **)&rt, &fl, false);
-       rcu_read_unlock();
 
        if (rt != NULL) {
                mtu = dst_mtu(&rt->dst);
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index df7f1df..1790773 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -70,13 +70,12 @@ tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, 
__be32 daddr)
                return user_laddr;
 
        laddr = 0;
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        indev = __in_dev_get_rcu(skb->dev);
        for_primary_ifa(indev) {
                laddr = ifa->ifa_local;
                break;
        } endfor_ifa(indev);
-       rcu_read_unlock();
 
        return laddr ? laddr : daddr;
 }
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c
index e329dab..cec7e76 100644
--- a/net/netfilter/xt_addrtype.c
+++ b/net/netfilter/xt_addrtype.c
@@ -47,8 +47,8 @@ static u32 match_lookup_rt6(struct net *net, const struct 
net_device *dev,
        if (dev)
                flow.flowi6_oif = dev->ifindex;
 
-       rcu_read_lock();
 
+       /* rcu_read_lock()ed by nf_hook */
        afinfo = nf_get_afinfo(NFPROTO_IPV6);
        if (afinfo != NULL) {
                const struct nf_ipv6_ops *v6ops;
@@ -63,7 +63,6 @@ static u32 match_lookup_rt6(struct net *net, const struct 
net_device *dev,
        } else {
                route_err = 1;
        }
-       rcu_read_unlock();
 
        if (route_err)
                return XT_ADDRTYPE_UNREACHABLE;
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index b8fd4ab..97589b8 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -144,7 +144,6 @@ static unsigned int check_hlist(struct net *net,
        unsigned int length = 0;
 
        *addit = true;
-       rcu_read_lock();
 
        /* check the saved connections */
        hlist_for_each_entry_safe(conn, n, head, node) {
@@ -179,8 +178,6 @@ static unsigned int check_hlist(struct net *net,
                length++;
        }
 
-       rcu_read_unlock();
-
        return length;
 }
 
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 762e187..8ffe05e 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -659,12 +659,13 @@ hashlimit_mt_common(const struct sk_buff *skb, struct 
xt_action_param *par,
        if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
                goto hotdrop;
 
-       rcu_read_lock_bh();
+       local_bh_disable();
+       /* rcu_read_lock()ed by nf_hook */
        dh = dsthash_find(hinfo, &dst);
        if (dh == NULL) {
                dh = dsthash_alloc_init(hinfo, &dst, &race);
                if (dh == NULL) {
-                       rcu_read_unlock_bh();
+                       local_bh_enable();
                        goto hotdrop;
                } else if (race) {
                        /* Already got an entry, update expiration timeout */
@@ -689,12 +690,12 @@ hashlimit_mt_common(const struct sk_buff *skb, struct 
xt_action_param *par,
                /* below the limit */
                dh->rateinfo.credit -= cost;
                spin_unlock(&dh->lock);
-               rcu_read_unlock_bh();
+               local_bh_enable();
                return !(cfg->mode & XT_HASHLIMIT_INVERT);
        }
 
        spin_unlock(&dh->lock);
-       rcu_read_unlock_bh();
+       local_bh_enable();
        /* default match is underlimit - so over the limit, we need to invert */
        return cfg->mode & XT_HASHLIMIT_INVERT;
 
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index c05fefc..f4c48b51 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -224,7 +224,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct 
xt_action_param *p)
                                sizeof(struct tcphdr), optsize, opts);
        }
 
-       rcu_read_lock();
+       /* rcu_read_lock()ed by nf_hook */
        list_for_each_entry_rcu(kf, &xt_osf_fingers[df], finger_entry) {
                int foptsize, optnum;
 
@@ -338,7 +338,6 @@ xt_osf_match_packet(const struct sk_buff *skb, struct 
xt_action_param *p)
                    info->loglevel == XT_OSF_LOGLEVEL_FIRST)
                        break;
        }
-       rcu_read_unlock();
 
        if (!fcount && (info->flags & XT_OSF_LOG))
                nf_log_packet(net, xt_family(p), xt_hooknum(p), skb, xt_in(p),
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to