| From 71a265419348c2ba9a8b7b24e16aded3dd4fd954 Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Fri, 20 Sep 2019 21:54:17 +0200 |
| Subject: [PATCH] nl80211: validate beacon head |
| |
| commit f88eb7c0d002a67ef31aeb7850b42ff69abc46dc 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: ed1b6cc7f80f ("cfg80211/nl80211: add beacon settings") |
| Link: https://lore.kernel.org/r/1569009255-I7ac7fbe9436e9d8733439eab8acbbd35e55c74ef@changeid |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c |
| index b28aaddbe08e..73891b7c2f8b 100644 |
| --- a/net/wireless/nl80211.c |
| +++ b/net/wireless/nl80211.c |
| @@ -201,6 +201,38 @@ cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) |
| 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, |
| struct netlink_ext_ack *extack) |
| { |
| @@ -322,8 +354,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { |
| |
| [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, |
| [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, |
| - [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, |
| - .len = IEEE80211_MAX_DATA_LEN }, |
| + [NL80211_ATTR_BEACON_HEAD] = |
| + NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head, |
| + IEEE80211_MAX_DATA_LEN), |
| [NL80211_ATTR_BEACON_TAIL] = |
| NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, |
| IEEE80211_MAX_DATA_LEN), |
| -- |
| 2.7.4 |
| |