|
|
@@ -0,0 +1,116 @@
|
|
|
+fixes ACL race condition caused by acl list modifications at run time
|
|
|
+
|
|
|
+Signed-off-by: Sebastian Gottschall <[email protected]>
|
|
|
+
|
|
|
+--- a/net80211/ieee80211_acl.c
|
|
|
++++ b/net80211/ieee80211_acl.c
|
|
|
+@@ -112,9 +112,9 @@ acl_detach(struct ieee80211vap *vap)
|
|
|
+ {
|
|
|
+ struct aclstate *as = vap->iv_as;
|
|
|
+
|
|
|
+- ACL_LOCK(as);
|
|
|
++ ACL_LOCK_IRQ(as);
|
|
|
+ acl_free_all_locked(as);
|
|
|
+- ACL_UNLOCK(as);
|
|
|
++ ACL_UNLOCK_IRQ(as);
|
|
|
+ vap->iv_as = NULL;
|
|
|
+ ACL_LOCK_DESTROY(as);
|
|
|
+ FREE(as, M_DEVBUF);
|
|
|
+@@ -128,11 +128,18 @@ _find_acl(struct aclstate *as, const u_i
|
|
|
+ struct acl *acl;
|
|
|
+ int hash;
|
|
|
+
|
|
|
++ /* locking needed, as inserts are not atomic */
|
|
|
++ ACL_LOCK_IRQ(as);
|
|
|
+ hash = ACL_HASH(macaddr);
|
|
|
+ LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
|
|
|
+- if (IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
|
|
|
+- return acl;
|
|
|
++ if (!IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
|
|
|
++ continue;
|
|
|
++
|
|
|
++ ACL_UNLOCK_IRQ_EARLY(as);
|
|
|
++ return acl;
|
|
|
+ }
|
|
|
++ ACL_UNLOCK_IRQ(as);
|
|
|
++
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -176,11 +183,11 @@ acl_add(struct ieee80211vap *vap, const
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+- ACL_LOCK(as);
|
|
|
++ ACL_LOCK_IRQ(as);
|
|
|
+ hash = ACL_HASH(mac);
|
|
|
+ LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
|
|
|
+ if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
|
|
|
+- ACL_UNLOCK_EARLY(as);
|
|
|
++ ACL_UNLOCK_IRQ_EARLY(as);
|
|
|
+ FREE(new, M_80211_ACL);
|
|
|
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
|
|
|
+ "ACL: add " MAC_FMT " failed, already present\n",
|
|
|
+@@ -191,7 +198,7 @@ acl_add(struct ieee80211vap *vap, const
|
|
|
+ IEEE80211_ADDR_COPY(new->acl_macaddr, mac);
|
|
|
+ TAILQ_INSERT_TAIL(&as->as_list, new, acl_list);
|
|
|
+ LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash);
|
|
|
+- ACL_UNLOCK(as);
|
|
|
++ ACL_UNLOCK_IRQ(as);
|
|
|
+
|
|
|
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
|
|
|
+ "ACL: add " MAC_FMT "\n", MAC_ADDR(mac));
|
|
|
+@@ -204,11 +211,11 @@ acl_remove(struct ieee80211vap *vap, con
|
|
|
+ struct aclstate *as = vap->iv_as;
|
|
|
+ struct acl *acl;
|
|
|
+
|
|
|
+- ACL_LOCK(as);
|
|
|
++ ACL_LOCK_IRQ(as);
|
|
|
+ acl = _find_acl(as, mac);
|
|
|
+ if (acl != NULL)
|
|
|
+ _acl_free(as, acl);
|
|
|
+- ACL_UNLOCK(as);
|
|
|
++ ACL_UNLOCK_IRQ(as);
|
|
|
+
|
|
|
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
|
|
|
+ "ACL: remove " MAC_FMT "%s\n", MAC_ADDR(mac),
|
|
|
+@@ -235,9 +242,9 @@ acl_free_all(struct ieee80211vap *vap)
|
|
|
+
|
|
|
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL, "ACL: %s\n", "free all");
|
|
|
+
|
|
|
+- ACL_LOCK(as);
|
|
|
++ ACL_LOCK_IRQ(as);
|
|
|
+ acl_free_all_locked(vap->iv_as);
|
|
|
+- ACL_UNLOCK(as);
|
|
|
++ ACL_UNLOCK_IRQ(as);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+--- a/net80211/ieee80211_linux.h
|
|
|
++++ b/net80211/ieee80211_linux.h
|
|
|
+@@ -311,16 +311,15 @@ typedef spinlock_t ieee80211_scan_lock_t
|
|
|
+ typedef spinlock_t acl_lock_t;
|
|
|
+ #define ACL_LOCK_INIT(_as, _name) spin_lock_init(&(_as)->as_lock)
|
|
|
+ #define ACL_LOCK_DESTROY(_as)
|
|
|
+-#define ACL_LOCK(_as) do { \
|
|
|
+- ACL_LOCK_CHECK(_as); \
|
|
|
+- spin_lock(&(_as)->as_lock);
|
|
|
+-#define ACL_UNLOCK(_as) \
|
|
|
+- ACL_LOCK_ASSERT(_as); \
|
|
|
+- spin_unlock(&(_as)->as_lock); \
|
|
|
+-} while(0)
|
|
|
+-#define ACL_UNLOCK_EARLY(_as) \
|
|
|
+- ACL_LOCK_ASSERT(_as); \
|
|
|
+- spin_unlock(&(_as)->as_lock);
|
|
|
++#define ACL_LOCK_IRQ(_as) do { \
|
|
|
++ unsigned long __acl_lockflags; \
|
|
|
++ spin_lock_irqsave(&(_as)->as_lock, __acl_lockflags);
|
|
|
++#define ACL_UNLOCK_IRQ(_as) \
|
|
|
++ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
|
|
|
++} while (0)
|
|
|
++#define ACL_UNLOCK_IRQ_EARLY(_as) do { \
|
|
|
++ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
|
|
|
++} while (0)
|
|
|
+
|
|
|
+ #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
|
|
|
+ #define ACL_LOCK_ASSERT(_as) \
|