Root/package/madwifi/patches/386-acl_crashfix.patch

1fixes ACL race condition caused by acl list modifications at run time
2
3Signed-off-by: Sebastian Gottschall <brainslayer@dd-wrt.com>
4
5--- a/net80211/ieee80211_acl.c
6+++ b/net80211/ieee80211_acl.c
7@@ -112,9 +112,9 @@ acl_detach(struct ieee80211vap *vap)
8 {
9     struct aclstate *as = vap->iv_as;
10 
11- ACL_LOCK(as);
12+ ACL_LOCK_IRQ(as);
13     acl_free_all_locked(as);
14- ACL_UNLOCK(as);
15+ ACL_UNLOCK_IRQ(as);
16     vap->iv_as = NULL;
17     ACL_LOCK_DESTROY(as);
18     FREE(as, M_DEVBUF);
19@@ -128,11 +128,18 @@ _find_acl(struct aclstate *as, const u_i
20     struct acl *acl;
21     int hash;
22 
23+ /* locking needed, as inserts are not atomic */
24+ ACL_LOCK_IRQ(as);
25     hash = ACL_HASH(macaddr);
26     LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
27- if (IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
28- return acl;
29+ if (!IEEE80211_ADDR_EQ(acl->acl_macaddr, macaddr))
30+ continue;
31+
32+ ACL_UNLOCK_IRQ_EARLY(as);
33+ return acl;
34     }
35+ ACL_UNLOCK_IRQ(as);
36+
37     return NULL;
38 }
39 
40@@ -176,11 +183,11 @@ acl_add(struct ieee80211vap *vap, const
41         return -ENOMEM;
42     }
43 
44- ACL_LOCK(as);
45+ ACL_LOCK_IRQ(as);
46     hash = ACL_HASH(mac);
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);
58- ACL_UNLOCK(as);
59+ ACL_UNLOCK_IRQ(as);
60 
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;
65     struct acl *acl;
66 
67- ACL_LOCK(as);
68+ ACL_LOCK_IRQ(as);
69     acl = _find_acl(as, mac);
70     if (acl != NULL)
71         _acl_free(as, acl);
72- ACL_UNLOCK(as);
73+ ACL_UNLOCK_IRQ(as);
74 
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)
78 
79     IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL, "ACL: %s\n", "free all");
80 
81- ACL_LOCK(as);
82+ ACL_LOCK_IRQ(as);
83     acl_free_all_locked(vap->iv_as);
84- ACL_UNLOCK(as);
85+ ACL_UNLOCK_IRQ(as);
86 
87     return 0;
88 }
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); \
101-} while(0)
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); \
110+} while (0)
111+#define ACL_UNLOCK_IRQ_EARLY(_as) do { \
112+ spin_unlock_irqrestore(&(_as)->as_lock, __acl_lockflags); \
113+} while (0)
114 
115 #if (defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)) && defined(spin_is_locked)
116 #define ACL_LOCK_ASSERT(_as) \
117

Archive Download this file



interactive