From 90cdd3cda25c21295ca5b54297f970b25bd02f84 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Tue, 18 Oct 2016 11:28:10 -0700 Subject: [PATCH] qcacld-3.0: Acquire read lock before accessing the address list This is a qcacld-2.0 to qcacld-3.0 propagation. WLAN host driver access the inet6_dev address list without acquiring the read lock, if the kernel network stack deletes the address while driver is accessing the list, it can lead to referencing already freed address by the driver. Hence, fix is to take the read lock before accessing the address list. Change-Id: I934e9f2039f3ab8540e439b9e8a87efced98807c CRs-Fixed: 1048897 --- core/hdd/src/wlan_hdd_power.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 207fbe78554c..c4dfdcb7666e 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -304,9 +304,12 @@ static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev, struct list_head *p; uint32_t scope; + read_lock_bh(&idev->lock); list_for_each(p, &idev->addr_list) { - if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) + if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { + read_unlock_bh(&idev->lock); return -EINVAL; + } ifa = list_entry(p, struct inet6_ifaddr, if_list); if (ifa->flags & IFA_F_DADFAILED) continue; @@ -326,6 +329,8 @@ static int hdd_fill_ipv6_uc_addr(struct inet6_dev *idev, hdd_err("The Scope %d is not supported", scope); } } + + read_unlock_bh(&idev->lock); return 0; } @@ -347,9 +352,12 @@ static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev, struct ifacaddr6 *ifaca; uint32_t scope; + read_lock_bh(&idev->lock); for (ifaca = idev->ac_list; ifaca; ifaca = ifaca->aca_next) { - if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) + if (*count >= SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA) { + read_unlock_bh(&idev->lock); return -EINVAL; + } /* For anycast addr no DAD */ scope = ipv6_addr_src_scope(&ifaca->aca_addr); switch (scope) { @@ -367,6 +375,8 @@ static int hdd_fill_ipv6_ac_addr(struct inet6_dev *idev, hdd_err("The Scope %d is not supported", scope); } } + + read_unlock_bh(&idev->lock); return 0; }