summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-09-20 15:54:17 -0400
committerJohannes Berg <johannes.berg@intel.com>2019-10-01 11:56:18 -0400
commitf88eb7c0d002a67ef31aeb7850b42ff69abc46dc (patch)
treee441fc47971730e402535959123f311151ce331e
parent68ce6688a5baefde30914fc07fc27292dbbe8320 (diff)
nl80211: validate beacon head
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>
-rw-r--r--net/wireless/nl80211.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d21b1581a665..7386421e2ad3 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)
201 return __cfg80211_rdev_from_attrs(netns, info->attrs); 201 return __cfg80211_rdev_from_attrs(netns, info->attrs);
202} 202}
203 203
204static int validate_beacon_head(const struct nlattr *attr,
205 struct netlink_ext_ack *extack)
206{
207 const u8 *data = nla_data(attr);
208 unsigned int len = nla_len(attr);
209 const struct element *elem;
210 const struct ieee80211_mgmt *mgmt = (void *)data;
211 unsigned int fixedlen = offsetof(struct ieee80211_mgmt,
212 u.beacon.variable);
213
214 if (len < fixedlen)
215 goto err;
216
217 if (ieee80211_hdrlen(mgmt->frame_control) !=
218 offsetof(struct ieee80211_mgmt, u.beacon))
219 goto err;
220
221 data += fixedlen;
222 len -= fixedlen;
223
224 for_each_element(elem, data, len) {
225 /* nothing */
226 }
227
228 if (for_each_element_completed(elem, data, len))
229 return 0;
230
231err:
232 NL_SET_ERR_MSG_ATTR(extack, attr, "malformed beacon head");
233 return -EINVAL;
234}
235
204static int validate_ie_attr(const struct nlattr *attr, 236static int validate_ie_attr(const struct nlattr *attr,
205 struct netlink_ext_ack *extack) 237 struct netlink_ext_ack *extack)
206{ 238{
@@ -338,8 +370,9 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
338 370
339 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 371 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
340 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 372 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
341 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY, 373 [NL80211_ATTR_BEACON_HEAD] =
342 .len = IEEE80211_MAX_DATA_LEN }, 374 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_beacon_head,
375 IEEE80211_MAX_DATA_LEN),
343 [NL80211_ATTR_BEACON_TAIL] = 376 [NL80211_ATTR_BEACON_TAIL] =
344 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr, 377 NLA_POLICY_VALIDATE_FN(NLA_BINARY, validate_ie_attr,
345 IEEE80211_MAX_DATA_LEN), 378 IEEE80211_MAX_DATA_LEN),