From: Liping Zhang <zlpnob...@gmail.com>

inet6_dev->addr_list is protected by inet6_dev->lock, so only using
rcu_read_lock is not enough, we should acquire read_lock_bh(&idev->lock)
before the inet6_dev->addr_list traversal.

Signed-off-by: Liping Zhang <zlpnob...@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>
---
 net/netfilter/nf_nat_redirect.c | 2 ++
 net/netfilter/xt_TPROXY.c       | 5 ++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_nat_redirect.c b/net/netfilter/nf_nat_redirect.c
index d43869879fcf..86067560a318 100644
--- a/net/netfilter/nf_nat_redirect.c
+++ b/net/netfilter/nf_nat_redirect.c
@@ -101,11 +101,13 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct 
nf_nat_range *range,
                rcu_read_lock();
                idev = __in6_dev_get(skb->dev);
                if (idev != NULL) {
+                       read_lock_bh(&idev->lock);
                        list_for_each_entry(ifa, &idev->addr_list, if_list) {
                                newdst = ifa->addr;
                                addr = true;
                                break;
                        }
+                       read_unlock_bh(&idev->lock);
                }
                rcu_read_unlock();
 
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 80cb7babeb64..df7f1df00330 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -393,7 +393,8 @@ tproxy_laddr6(struct sk_buff *skb, const struct in6_addr 
*user_laddr,
 
        rcu_read_lock();
        indev = __in6_dev_get(skb->dev);
-       if (indev)
+       if (indev) {
+               read_lock_bh(&indev->lock);
                list_for_each_entry(ifa, &indev->addr_list, if_list) {
                        if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
                                continue;
@@ -401,6 +402,8 @@ tproxy_laddr6(struct sk_buff *skb, const struct in6_addr 
*user_laddr,
                        laddr = &ifa->addr;
                        break;
                }
+               read_unlock_bh(&indev->lock);
+       }
        rcu_read_unlock();
 
        return laddr ? laddr : daddr;
-- 
2.1.4

Reply via email to