More fixes:

* hwsim:
     - properly flush deletion works at module unload
     - validate # of channels passed from userspace
  * cfg80211:
     - fix RCU locking regression
     - initialize on-stack channel data for nl80211 event
     - check dev_set_name() return value
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAlpch0kACgkQB8qZga/f
 l8R3dg/+IkRShxLcSrig3u8o24gWgEYP01y98gtW0eSe2kuWkC4lMYejSg/Wa/7F
 2w6kLyZwXpUxiHqyrcZpZG6xxcBklL77TfxiTnscWdC/ubcKHHRQrcsIglKcuFeN
 jpogCOVS3F0xFxdssKBJoLMYRkb4ZXAa3GN9/2x5M9dWQRBE5ixtx23iy85YGXyk
 xyhAXvGqdk0PKWj63G65dCKxISWVunAWxnXZh5KfKySNzPiuYf6zlDHRGUY7AhVb
 ZD5FeFI0tledoYoCpqNRuDcjfi1z3jUCINb1IVsA7LaXCiJRDW0PmhWE1KDNoREU
 Zono6ytEdt9tLMCNrZ8Gi2FZvIkLD0SCYMkkduIGyrXgDMB37H1HctkFa+YK2C/E
 TxfKZYPChIT9lVczVRySz69fzp9twALKwQO8AAQzi7eWNLQ8ztJnVvF6vMIVHODh
 DSWfHdfqIEaIiku4mcV/Urd3xGm6JTHgQExyfA5VkRDkMIQdpWWQv9pUsKGAswtp
 x5KjV6ytbWwzwULXY1StDalG0S+jWk3G/4Cin8FQH4VbbfWlUyE/azT+549GReuj
 wlU9wgIWGA8s1qzHj/vUlTqW0GOLob5uvbq5HdfHvzhbP89PJz+DriU5mKgJS1uL
 80PS+ocLJSvWQFc9Ep65LpKTU6FHdrFrRl6ZBwk6E2lYLEOzs6c=
 =xGDk
 -----END PGP SIGNATURE-----

Merge tag 'mac80211-for-davem-2018-01-15' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
More fixes:
 * hwsim:
    - properly flush deletion works at module unload
    - validate # of channels passed from userspace
 * cfg80211:
    - fix RCU locking regression
    - initialize on-stack channel data for nl80211 event
    - check dev_set_name() return value
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2018-01-16 14:28:14 -05:00
commit 161f72ed6d
6 changed files with 32 additions and 11 deletions

View File

@ -489,6 +489,7 @@ static const struct ieee80211_iface_combination hwsim_if_comb_p2p_dev[] = {
static spinlock_t hwsim_radio_lock; static spinlock_t hwsim_radio_lock;
static LIST_HEAD(hwsim_radios); static LIST_HEAD(hwsim_radios);
static struct workqueue_struct *hwsim_wq;
static int hwsim_radio_idx; static int hwsim_radio_idx;
static struct platform_driver mac80211_hwsim_driver = { static struct platform_driver mac80211_hwsim_driver = {
@ -3120,6 +3121,11 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
if (info->attrs[HWSIM_ATTR_CHANNELS]) if (info->attrs[HWSIM_ATTR_CHANNELS])
param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
if (param.channels > CFG80211_MAX_NUM_DIFFERENT_CHANNELS) {
GENL_SET_ERR_MSG(info, "too many channels specified");
return -EINVAL;
}
if (info->attrs[HWSIM_ATTR_NO_VIF]) if (info->attrs[HWSIM_ATTR_NO_VIF])
param.no_vif = true; param.no_vif = true;
@ -3342,7 +3348,7 @@ static void remove_user_radios(u32 portid)
if (entry->destroy_on_close && entry->portid == portid) { if (entry->destroy_on_close && entry->portid == portid) {
list_del(&entry->list); list_del(&entry->list);
INIT_WORK(&entry->destroy_work, destroy_radio); INIT_WORK(&entry->destroy_work, destroy_radio);
schedule_work(&entry->destroy_work); queue_work(hwsim_wq, &entry->destroy_work);
} }
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
@ -3417,7 +3423,7 @@ static void __net_exit hwsim_exit_net(struct net *net)
list_del(&data->list); list_del(&data->list);
INIT_WORK(&data->destroy_work, destroy_radio); INIT_WORK(&data->destroy_work, destroy_radio);
schedule_work(&data->destroy_work); queue_work(hwsim_wq, &data->destroy_work);
} }
spin_unlock_bh(&hwsim_radio_lock); spin_unlock_bh(&hwsim_radio_lock);
} }
@ -3449,6 +3455,10 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init(&hwsim_radio_lock); spin_lock_init(&hwsim_radio_lock);
hwsim_wq = alloc_workqueue("hwsim_wq",WQ_MEM_RECLAIM,0);
if (!hwsim_wq)
return -ENOMEM;
err = register_pernet_device(&hwsim_net_ops); err = register_pernet_device(&hwsim_net_ops);
if (err) if (err)
return err; return err;
@ -3587,8 +3597,11 @@ static void __exit exit_mac80211_hwsim(void)
hwsim_exit_netlink(); hwsim_exit_netlink();
mac80211_hwsim_free(); mac80211_hwsim_free();
flush_workqueue(hwsim_wq);
unregister_netdev(hwsim_mon); unregister_netdev(hwsim_mon);
platform_driver_unregister(&mac80211_hwsim_driver); platform_driver_unregister(&mac80211_hwsim_driver);
unregister_pernet_device(&hwsim_net_ops); unregister_pernet_device(&hwsim_net_ops);
destroy_workqueue(hwsim_wq);
} }
module_exit(exit_mac80211_hwsim); module_exit(exit_mac80211_hwsim);

View File

@ -815,6 +815,8 @@ struct cfg80211_csa_settings {
u8 count; u8 count;
}; };
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
/** /**
* struct iface_combination_params - input parameters for interface combinations * struct iface_combination_params - input parameters for interface combinations
* *

View File

@ -439,6 +439,8 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
if (rv) if (rv)
goto use_default_name; goto use_default_name;
} else { } else {
int rv;
use_default_name: use_default_name:
/* NOTE: This is *probably* safe w/out holding rtnl because of /* NOTE: This is *probably* safe w/out holding rtnl because of
* the restrictions on phy names. Probably this call could * the restrictions on phy names. Probably this call could
@ -446,7 +448,11 @@ use_default_name:
* phyX. But, might should add some locking and check return * phyX. But, might should add some locking and check return
* value, and use a different name if this one exists? * value, and use a different name if this one exists?
*/ */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); rv = dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
if (rv < 0) {
kfree(rdev);
return NULL;
}
} }
INIT_LIST_HEAD(&rdev->wiphy.wdev_list); INIT_LIST_HEAD(&rdev->wiphy.wdev_list);

View File

@ -507,8 +507,6 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev); struct wireless_dev *wdev);
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
#else #else

View File

@ -2618,12 +2618,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
const u8 *ssid_ie; const u8 *ssid_ie;
if (!wdev->current_bss) if (!wdev->current_bss)
break; break;
rcu_read_lock();
ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub, ssid_ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
WLAN_EID_SSID); WLAN_EID_SSID);
if (!ssid_ie) if (ssid_ie &&
break; nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2))
if (nla_put(msg, NL80211_ATTR_SSID, ssid_ie[1], ssid_ie + 2)) goto nla_put_failure_rcu_locked;
goto nla_put_failure_locked; rcu_read_unlock();
break; break;
} }
default: default:
@ -2635,6 +2636,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
return 0; return 0;
nla_put_failure_rcu_locked:
rcu_read_unlock();
nla_put_failure_locked: nla_put_failure_locked:
wdev_unlock(wdev); wdev_unlock(wdev);
nla_put_failure: nla_put_failure:

View File

@ -1769,8 +1769,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS) if (wiphy->regulatory_flags & REGULATORY_DISABLE_BEACON_HINTS)
return; return;
chan_before.center_freq = chan->center_freq; chan_before = *chan;
chan_before.flags = chan->flags;
if (chan->flags & IEEE80211_CHAN_NO_IR) { if (chan->flags & IEEE80211_CHAN_NO_IR) {
chan->flags &= ~IEEE80211_CHAN_NO_IR; chan->flags &= ~IEEE80211_CHAN_NO_IR;