1 fixes ACL race condition caused by acl list modifications at run time
3 Signed-off-by: Sebastian Gottschall <brainslayer@dd-wrt.com>
5 --- a/net80211/ieee80211_acl.c
6 +++ b/net80211/ieee80211_acl.c
7 @@ -112,9 +112,9 @@ acl_detach(struct ieee80211vap *vap)
9 struct aclstate *as = vap->iv_as;
13 acl_free_all_locked(as);
19 @@ -128,11 +128,18 @@ _find_acl(struct aclstate *as, const u_i
23 + /* locking needed, as inserts are not atomic */
25 hash = ACL_HASH(macaddr);
26 LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
27 - if (IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
29 + if (!IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
32 + ACL_UNLOCK_IRQ_EARLY(as);
40 @@ -176,11 +183,11 @@ acl_add(struct ieee80211vap *vap, const
47 LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
48 if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
49 - ACL_UNLOCK_EARLY(as);
50 + ACL_UNLOCK_IRQ_EARLY(as);
51 FREE(new, M_80211_ACL);
52 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
53 "ACL: add " MAC_FMT " failed, already present\n",
54 @@ -191,7 +198,7 @@ acl_add(struct ieee80211vap *vap, const
55 IEEE80211_ADDR_COPY(new->acl_macaddr, mac);
56 TAILQ_INSERT_TAIL(&as->as_list, new, acl_list);
57 LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash);
61 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
62 "ACL: add " MAC_FMT "\n", MAC_ADDR(mac));
63 @@ -204,11 +211,11 @@ acl_remove(struct ieee80211vap *vap, con
64 struct aclstate *as = vap->iv_as;
69 acl = _find_acl(as, mac);
75 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
76 "ACL: remove " MAC_FMT "%s\n", MAC_ADDR(mac),
77 @@ -235,9 +242,9 @@ acl_free_all(struct ieee80211vap *vap)
79 IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL, "ACL: %s\n", "free all");
83 acl_free_all_locked(vap->iv_as);
89 --- a/net80211/ieee80211_linux.h
90 +++ b/net80211/ieee80211_linux.h
91 @@ -319,16 +319,15 @@ typedef spinlock_t ieee80211_scan_lock_t
92 typedef spinlock_t acl_lock_t;
93 #define ACL_LOCK_INIT(_as, _name) spin_lock_init(&(_as)->as_lock)
94 #define ACL_LOCK_DESTROY(_as)
95 -#define ACL_LOCK(_as) do { \
96 - ACL_LOCK_CHECK(_as); \
97 - spin_lock(&(_as)->as_lock);
98 -#define ACL_UNLOCK(_as) \
99 - ACL_LOCK_ASSERT(_as); \
100 - spin_unlock(&(_as)->as_lock); \
102 -#define ACL_UNLOCK_EARLY(_as) \
103 - ACL_LOCK_ASSERT(_as); \
104 - spin_unlock(&(_as)->as_lock);
105 +#define ACL_LOCK_IRQ(_as) do { \
106 + unsigned long __acl_lockflags; \
107 + spin_lock_irqsave(&(_as)->as_lock, __acl_lockflags);
108 +#define ACL_UNLOCK_IRQ(_as) \
109 + spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
111 +#define ACL_UNLOCK_IRQ_EARLY(_as) do { \
112 + spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
115 #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
116 #define ACL_LOCK_ASSERT(_as) \