Commit 06163fd2 authored by Johannes Berg's avatar Johannes Berg Committed by Khalid Elmously

nl80211: validate beacon head

BugLink: https://bugs.launchpad.net/bugs/1848780

commit f88eb7c0 upstream.

We currently don't validate the beacon head, i.e. the header,
fixed part and elements that are to go in front of the TIM
element. This means that the variable elements there can be
malformed, e.g. have a length exceeding the buffer size, but
most downstream code from this assumes that this has already
been checked.

Add the necessary checks to the netlink policy.

Cc: stable@vger.kernel.org
Fixes: ed1b6cc7 ("cfg80211/nl80211: add beacon settings")
Link: https://lore.kernel.org/r/1569009255-I7ac7fbe9436e9d8733439eab8acbbd35e55c74ef@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarConnor Kuehl <connor.kuehl@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent 68f64a92
...@@ -210,6 +210,36 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) ...@@ -210,6 +210,36 @@ 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)
{
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:
return -EINVAL;
}
/* policy for the attributes */ /* policy for the attributes */
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
...@@ -3214,6 +3244,11 @@ static int nl80211_parse_beacon(struct nlattr *attrs[], ...@@ -3214,6 +3244,11 @@ static int nl80211_parse_beacon(struct nlattr *attrs[],
memset(bcn, 0, sizeof(*bcn)); memset(bcn, 0, sizeof(*bcn));
if (attrs[NL80211_ATTR_BEACON_HEAD]) { if (attrs[NL80211_ATTR_BEACON_HEAD]) {
int ret = validate_beacon_head(attrs[NL80211_ATTR_BEACON_HEAD]);
if (ret)
return ret;
bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]);
bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]);
if (!bcn->head_len) if (!bcn->head_len)
......
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