[PATCH] [madwifi] Fix device name allocation
[openwrt.git] / package / madwifi / patches / 386-acl_crashfix.patch
1 fixes ACL race condition caused by acl list modifications at run time
2
3 Signed-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) \