2011-03-28 11:32:45

by Juuso Oikarinen

[permalink] [raw]
Subject: [PATCHv2] cfg80211: fix BSS double-unlinking (continued)

From: Juuso Oikarinen <[email protected]>

This patch adds to the fix "fix BSS double-unlinking"
(commit 3207390a8b58bfc1335750f91cf6783c48ca19ca) by Johannes Berg.

It turns out, that the double-unlinking scenario can also occur if expired
BSS elements are removed whilst an interface is performing association.

To work around that, replace list_del with list_del_init also in the
"cfg80211_bss_expire" function, so that the check for whether the BSS still is
in the list works correctly in cfg80211_unlink_bss.

Signed-off-by: Juuso Oikarinen <[email protected]>
---
v2: Small correction in patch title, separate function for the actual
unlinking of the bss

net/wireless/scan.c | 18 +++++++++++-------
1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ea427f4..0be7b46 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -124,6 +124,15 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev,
}

/* must hold dev->bss_lock! */
+static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
+ struct cfg80211_internal_bss *bss)
+{
+ list_del_init(&bss->list);
+ rb_erase(&bss->rbn, &dev->bss_tree);
+ kref_put(&bss->ref, bss_release);
+}
+
+/* must hold dev->bss_lock! */
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
{
struct cfg80211_internal_bss *bss, *tmp;
@@ -134,9 +143,7 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
continue;
if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
continue;
- list_del(&bss->list);
- rb_erase(&bss->rbn, &dev->bss_tree);
- kref_put(&bss->ref, bss_release);
+ __cfg80211_unlink_bss(dev, bss);
expired = true;
}

@@ -662,11 +669,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)

spin_lock_bh(&dev->bss_lock);
if (!list_empty(&bss->list)) {
- list_del_init(&bss->list);
+ __cfg80211_unlink_bss(dev, bss);
dev->bss_generation++;
- rb_erase(&bss->rbn, &dev->bss_tree);
-
- kref_put(&bss->ref, bss_release);
}
spin_unlock_bh(&dev->bss_lock);
}
--
1.7.1



2011-03-28 12:14:28

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCHv2] cfg80211: fix BSS double-unlinking (continued)

On Mon, 2011-03-28 at 14:32 +0300, [email protected] wrote:
> From: Juuso Oikarinen <[email protected]>
>
> This patch adds to the fix "fix BSS double-unlinking"
> (commit 3207390a8b58bfc1335750f91cf6783c48ca19ca) by Johannes Berg.
>
> It turns out, that the double-unlinking scenario can also occur if expired
> BSS elements are removed whilst an interface is performing association.
>
> To work around that, replace list_del with list_del_init also in the
> "cfg80211_bss_expire" function, so that the check for whether the BSS still is
> in the list works correctly in cfg80211_unlink_bss.
>
> Signed-off-by: Juuso Oikarinen <[email protected]>

Reviewed-by: Johannes Berg <[email protected]>

Thanks.

johannes