Commit 9cfc3702 authored by David S. Miller's avatar David S. Miller

Merge tag 'mac80211-for-davem-2019-10-01' of...

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

Johannes Berg says:

====================
A small list of fixes this time:
 * two null pointer dereference fixes
 * a fix for preempt-enabled/BHs-enabled (lockdep) splats
   (that correctly pointed out a bug)
 * a fix for multi-BSSID ordering assumptions
 * a fix for the EDMG support, on-stack chandefs need to
   be initialized properly (now that they're bigger)
 * beacon (head) data from userspace should be validated
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6de6d185 d8dec42b
...@@ -487,9 +487,14 @@ static ssize_t ieee80211_if_fmt_aqm( ...@@ -487,9 +487,14 @@ static ssize_t ieee80211_if_fmt_aqm(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct txq_info *txqi = to_txq_info(sdata->vif.txq); struct txq_info *txqi;
int len; int len;
if (!sdata->vif.txq)
return 0;
txqi = to_txq_info(sdata->vif.txq);
spin_lock_bh(&local->fq.lock); spin_lock_bh(&local->fq.lock);
rcu_read_lock(); rcu_read_lock();
...@@ -658,7 +663,9 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata) ...@@ -658,7 +663,9 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz); DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
DEBUGFS_ADD(hw_queues); DEBUGFS_ADD(hw_queues);
if (sdata->local->ops->wake_tx_queue) if (sdata->local->ops->wake_tx_queue &&
sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
sdata->vif.type != NL80211_IFTYPE_NAN)
DEBUGFS_ADD(aqm); DEBUGFS_ADD(aqm);
} }
......
...@@ -247,7 +247,8 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) ...@@ -247,7 +247,8 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
struct sta_info *sta; struct sta_info *sta;
int i; int i;
spin_lock_bh(&fq->lock); local_bh_disable();
spin_lock(&fq->lock);
if (sdata->vif.type == NL80211_IFTYPE_AP) if (sdata->vif.type == NL80211_IFTYPE_AP)
ps = &sdata->bss->ps; ps = &sdata->bss->ps;
...@@ -273,9 +274,9 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) ...@@ -273,9 +274,9 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
&txqi->flags)) &txqi->flags))
continue; continue;
spin_unlock_bh(&fq->lock); spin_unlock(&fq->lock);
drv_wake_tx_queue(local, txqi); drv_wake_tx_queue(local, txqi);
spin_lock_bh(&fq->lock); spin_lock(&fq->lock);
} }
} }
...@@ -288,12 +289,14 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) ...@@ -288,12 +289,14 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
(ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac) (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac)
goto out; goto out;
spin_unlock_bh(&fq->lock); spin_unlock(&fq->lock);
drv_wake_tx_queue(local, txqi); drv_wake_tx_queue(local, txqi);
local_bh_enable();
return; return;
out: out:
spin_unlock_bh(&fq->lock); spin_unlock(&fq->lock);
local_bh_enable();
} }
static void static void
......
...@@ -201,6 +201,38 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) ...@@ -201,6 +201,38 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
return __cfg80211_rdev_from_attrs(netns, info->attrs); return __cfg80211_rdev_from_attrs(netns, info->attrs);
} }
static int validate_beacon_head(const struct nlattr *attr,
struct netlink_ext_ack *extack)
{
const u8 *data = nla_data(attr);
unsigned int len = nla_len(attr);
const struct element *elem;
const struct ieee80211_mgmt *mgmt = (void *)data;
unsigned int fixedlen = offsetof(struct ieee80211_mgmt,
u.beacon.variable);
if (len < fixedlen)
goto err;
if (ieee80211_hdrlen(mgmt->frame_control) !=
offsetof(struct ieee80211_mgmt, u.beacon))
goto err;
data += fixedlen;
len -= fixedlen;
for_each_element(elem, data, len) {
/* nothing */
}
if (for_each_element_completed(elem, data, len))
return 0;
err:
NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
return -EINVAL;
}
static int validate_ie_attr(const struct nlattr *attr, static int validate_ie_attr(const struct nlattr *attr,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
...@@ -338,8 +370,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { ...@@ -338,8 +370,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
[NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
[NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, [NL80211_ATTR_BEACON_HEAD] =
.len = IEEE80211_MAX_DATA_LEN }, NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
IEEE80211_MAX_DATA_LEN),
[NL80211_ATTR_BEACON_TAIL] = [NL80211_ATTR_BEACON_TAIL] =
NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
IEEE80211_MAX_DATA_LEN), IEEE80211_MAX_DATA_LEN),
...@@ -2636,6 +2669,8 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev, ...@@ -2636,6 +2669,8 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
control_freq = nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]); control_freq = nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]);
memset(chandef, 0, sizeof(*chandef));
chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq); chandef->chan = ieee80211_get_channel(&rdev->wiphy, control_freq);
chandef->width = NL80211_CHAN_WIDTH_20_NOHT; chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
chandef->center_freq1 = control_freq; chandef->center_freq1 = control_freq;
...@@ -3176,7 +3211,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag ...@@ -3176,7 +3211,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
if (rdev->ops->get_channel) { if (rdev->ops->get_channel) {
int ret; int ret;
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef = {};
ret = rdev_get_channel(rdev, wdev, &chandef); ret = rdev_get_channel(rdev, wdev, &chandef);
if (ret == 0) { if (ret == 0) {
...@@ -6270,6 +6305,9 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) ...@@ -6270,6 +6305,9 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->del_mpath) if (!rdev->ops->del_mpath)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
return -EOPNOTSUPP;
return rdev_del_mpath(rdev, dev, dst); return rdev_del_mpath(rdev, dev, dst);
} }
......
...@@ -2108,7 +2108,7 @@ static void reg_call_notifier(struct wiphy *wiphy, ...@@ -2108,7 +2108,7 @@ static void reg_call_notifier(struct wiphy *wiphy,
static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
{ {
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef = {};
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
enum nl80211_iftype iftype; enum nl80211_iftype iftype;
......
...@@ -1723,7 +1723,12 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, ...@@ -1723,7 +1723,12 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
return; return;
new_ie_len -= trans_ssid[1]; new_ie_len -= trans_ssid[1];
mbssid = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen); mbssid = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen);
if (!mbssid) /*
* It's not valid to have the MBSSID element before SSID
* ignore if that happens - the code below assumes it is
* after (while copying things inbetween).
*/
if (!mbssid || mbssid < trans_ssid)
return; return;
new_ie_len -= mbssid[1]; new_ie_len -= mbssid[1];
rcu_read_lock(); rcu_read_lock();
......
...@@ -798,7 +798,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, ...@@ -798,7 +798,7 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef = {};
int ret; int ret;
switch (wdev->iftype) { switch (wdev->iftype) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment