]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - net/mac80211/ieee80211_ioctl.c
mac80211: fix key vs. sta locking problems
[mirror_ubuntu-jammy-kernel.git] / net / mac80211 / ieee80211_ioctl.c
index 41130b3031709af8269c63f4f6b3184c6d33c900..a611c8bc76bd408ef8b00875644621767d979330 100644 (file)
@@ -36,6 +36,7 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
        struct sta_info *sta;
        struct ieee80211_key *key;
        struct ieee80211_sub_if_data *sdata;
+       int err;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -46,23 +47,31 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
        }
 
        if (remove) {
+               rcu_read_lock();
+
+               err = 0;
+
                if (is_broadcast_ether_addr(sta_addr)) {
                        key = sdata->keys[idx];
                } else {
                        sta = sta_info_get(local, sta_addr);
-                       if (!sta)
-                               return -ENOENT;
+                       if (!sta) {
+                               err = -ENOENT;
+                               goto out_unlock;
+                       }
                        key = sta->key;
                }
 
                ieee80211_key_free(key);
-               return 0;
        } else {
                key = ieee80211_key_alloc(alg, idx, key_len, _key);
                if (!key)
                        return -ENOMEM;
 
                sta = NULL;
+               err = 0;
+
+               rcu_read_lock();
 
                if (!is_broadcast_ether_addr(sta_addr)) {
                        set_tx_key = 0;
@@ -74,13 +83,15 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
                         */
                        if (idx != 0 && alg != ALG_WEP) {
                                ieee80211_key_free(key);
-                               return -EINVAL;
+                               err = -EINVAL;
+                               goto out_unlock;
                        }
 
                        sta = sta_info_get(local, sta_addr);
                        if (!sta) {
                                ieee80211_key_free(key);
-                               return -ENOENT;
+                               err = -ENOENT;
+                               goto out_unlock;
                        }
                }
 
@@ -90,7 +101,10 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
                        ieee80211_set_default_key(sdata, idx);
        }
 
-       return 0;
+ out_unlock:
+       rcu_read_unlock();
+
+       return err;
 }
 
 static int ieee80211_ioctl_siwgenie(struct net_device *dev,