cfg80211: off by one in nl80211_trigger_scan()
[firefly-linux-kernel-4.4.55.git] / net / wireless / core.c
index c22ef3492ee6f0b8f58f1d663c995a977a7bcc6b..645437cfc464d505a3673870f8c0a6eb73287535 100644 (file)
@@ -366,6 +366,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
 
        mutex_init(&rdev->mtx);
        mutex_init(&rdev->devlist_mtx);
+       mutex_init(&rdev->sched_scan_mtx);
        INIT_LIST_HEAD(&rdev->netdev_list);
        spin_lock_init(&rdev->bss_lock);
        INIT_LIST_HEAD(&rdev->bss_list);
@@ -487,6 +488,10 @@ int wiphy_register(struct wiphy *wiphy)
        int i;
        u16 ifmodes = wiphy->interface_modes;
 
+       if (WARN_ON((wiphy->wowlan.flags & WIPHY_WOWLAN_GTK_REKEY_FAILURE) &&
+                   !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
+               return -EINVAL;
+
        if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
                return -EINVAL;
 
@@ -701,6 +706,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
        rfkill_destroy(rdev->rfkill);
        mutex_destroy(&rdev->mtx);
        mutex_destroy(&rdev->devlist_mtx);
+       mutex_destroy(&rdev->sched_scan_mtx);
        list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
                cfg80211_put_bss(&scan->pub);
        cfg80211_rdev_free_wowlan(rdev);
@@ -737,12 +743,16 @@ static void wdev_cleanup_work(struct work_struct *work)
                ___cfg80211_scan_done(rdev, true);
        }
 
+       cfg80211_unlock_rdev(rdev);
+
+       mutex_lock(&rdev->sched_scan_mtx);
+
        if (WARN_ON(rdev->sched_scan_req &&
                    rdev->sched_scan_req->dev == wdev->netdev)) {
                __cfg80211_stop_sched_scan(rdev, false);
        }
 
-       cfg80211_unlock_rdev(rdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
 
        mutex_lock(&rdev->devlist_mtx);
        rdev->opencount--;
@@ -830,9 +840,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
                        break;
                case NL80211_IFTYPE_P2P_CLIENT:
                case NL80211_IFTYPE_STATION:
-                       cfg80211_lock_rdev(rdev);
+                       mutex_lock(&rdev->sched_scan_mtx);
                        __cfg80211_stop_sched_scan(rdev, false);
-                       cfg80211_unlock_rdev(rdev);
+                       mutex_unlock(&rdev->sched_scan_mtx);
 
                        wdev_lock(wdev);
 #ifdef CONFIG_CFG80211_WEXT
@@ -912,7 +922,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
                 * Configure power management to the driver here so that its
                 * correctly set also after interface type changes etc.
                 */
-               if (wdev->iftype == NL80211_IFTYPE_STATION &&
+               if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+                    wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
                    rdev->ops->set_power_mgmt)
                        if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
                                                      wdev->ps,