From: Greg Kroah-Hartman Date: Wed, 9 Oct 2019 13:41:07 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.14.149~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cc7808d94b8d4d0dcbe84d9cd589ead09524eeae;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch cfg80211-use-const-more-consistently-in-for_each_element-macros.patch nl80211-validate-beacon-head.patch --- diff --git a/queue-4.14/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch b/queue-4.14/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch new file mode 100644 index 00000000000..7585643bb85 --- /dev/null +++ b/queue-4.14/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch @@ -0,0 +1,134 @@ +From 0f3b07f027f87a38ebe5c436490095df762819be Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 7 Feb 2019 21:44:41 +0100 +Subject: cfg80211: add and use strongly typed element iteration macros + +From: Johannes Berg + +commit 0f3b07f027f87a38ebe5c436490095df762819be upstream. + +Rather than always iterating elements from frames with pure +u8 pointers, add a type "struct element" that encapsulates +the id/datalen/data format of them. + +Then, add the element iteration macros + * for_each_element + * for_each_element_id + * for_each_element_extid + +which take, as their first 'argument', such a structure and +iterate through a given u8 array interpreting it as elements. + +While at it and since we'll need it, also add + * for_each_subelement + * for_each_subelement_id + * for_each_subelement_extid + +which instead of taking data/length just take an outer element +and use its data/datalen. + +Also add for_each_element_completed() to determine if any of +the loops above completed, i.e. it was able to parse all of +the elements successfully and no data remained. + +Use for_each_element_id() in cfg80211_find_ie_match() as the +first user of this. + +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/ieee80211.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++ + net/wireless/scan.c | 14 +++++------- + 2 files changed, 59 insertions(+), 8 deletions(-) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2743,4 +2743,57 @@ static inline bool ieee80211_action_cont + return true; + } + ++struct element { ++ u8 id; ++ u8 datalen; ++ u8 data[]; ++}; ++ ++/* element iteration helpers */ ++#define for_each_element(element, _data, _datalen) \ ++ for (element = (void *)(_data); \ ++ (u8 *)(_data) + (_datalen) - (u8 *)element >= \ ++ sizeof(*element) && \ ++ (u8 *)(_data) + (_datalen) - (u8 *)element >= \ ++ sizeof(*element) + element->datalen; \ ++ element = (void *)(element->data + element->datalen)) ++ ++#define for_each_element_id(element, _id, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == (_id)) ++ ++#define for_each_element_extid(element, extid, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == WLAN_EID_EXTENSION && \ ++ element->datalen > 0 && \ ++ element->data[0] == (extid)) ++ ++#define for_each_subelement(sub, element) \ ++ for_each_element(sub, (element)->data, (element)->datalen) ++ ++#define for_each_subelement_id(sub, id, element) \ ++ for_each_element_id(sub, id, (element)->data, (element)->datalen) ++ ++#define for_each_subelement_extid(sub, extid, element) \ ++ for_each_element_extid(sub, extid, (element)->data, (element)->datalen) ++ ++/** ++ * for_each_element_completed - determine if element parsing consumed all data ++ * @element: element pointer after for_each_element() or friends ++ * @data: same data pointer as passed to for_each_element() or friends ++ * @datalen: same data length as passed to for_each_element() or friends ++ * ++ * This function returns %true if all the data was parsed or considered ++ * while walking the elements. Only use this if your for_each_element() ++ * loop cannot be broken out of, otherwise it always returns %false. ++ * ++ * If some data was malformed, this returns %false since the last parsed ++ * element will not fill the whole remaining data. ++ */ ++static inline bool for_each_element_completed(const struct element *element, ++ const void *data, size_t datalen) ++{ ++ return (u8 *)element == (u8 *)data + datalen; ++} ++ + #endif /* LINUX_IEEE80211_H */ +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -484,6 +484,8 @@ const u8 *cfg80211_find_ie_match(u8 eid, + const u8 *match, int match_len, + int match_offset) + { ++ const struct element *elem; ++ + /* match_offset can't be smaller than 2, unless match_len is + * zero, in which case match_offset must be zero as well. + */ +@@ -491,14 +493,10 @@ const u8 *cfg80211_find_ie_match(u8 eid, + (!match_len && match_offset))) + return NULL; + +- while (len >= 2 && len >= ies[1] + 2) { +- if ((ies[0] == eid) && +- (ies[1] + 2 >= match_offset + match_len) && +- !memcmp(ies + match_offset, match, match_len)) +- return ies; +- +- len -= ies[1] + 2; +- ies += ies[1] + 2; ++ for_each_element_id(elem, eid, ies, len) { ++ if (elem->datalen >= match_offset - 2 + match_len && ++ !memcmp(elem->data + match_offset - 2, match, match_len)) ++ return (void *)elem; + } + + return NULL; diff --git a/queue-4.14/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch b/queue-4.14/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch new file mode 100644 index 00000000000..53068ffe741 --- /dev/null +++ b/queue-4.14/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch @@ -0,0 +1,59 @@ +From 7388afe09143210f555bdd6c75035e9acc1fab96 Mon Sep 17 00:00:00 2001 +From: Jouni Malinen +Date: Mon, 11 Feb 2019 16:29:04 +0200 +Subject: cfg80211: Use const more consistently in for_each_element macros + +From: Jouni Malinen + +commit 7388afe09143210f555bdd6c75035e9acc1fab96 upstream. + +Enforce the first argument to be a correct type of a pointer to struct +element and avoid unnecessary typecasts from const to non-const pointers +(the change in validate_ie_attr() is needed to make this part work). In +addition, avoid signed/unsigned comparison within for_each_element() and +mark struct element packed just in case. + +Signed-off-by: Jouni Malinen +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/ieee80211.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2747,16 +2747,16 @@ struct element { + u8 id; + u8 datalen; + u8 data[]; +-}; ++} __packed; + + /* element iteration helpers */ +-#define for_each_element(element, _data, _datalen) \ +- for (element = (void *)(_data); \ +- (u8 *)(_data) + (_datalen) - (u8 *)element >= \ +- sizeof(*element) && \ +- (u8 *)(_data) + (_datalen) - (u8 *)element >= \ +- sizeof(*element) + element->datalen; \ +- element = (void *)(element->data + element->datalen)) ++#define for_each_element(_elem, _data, _datalen) \ ++ for (_elem = (const struct element *)(_data); \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) && \ ++ (const u8 *)(_data) + (_datalen) - (const u8 *)_elem >= \ ++ (int)sizeof(*_elem) + _elem->datalen; \ ++ _elem = (const struct element *)(_elem->data + _elem->datalen)) + + #define for_each_element_id(element, _id, data, datalen) \ + for_each_element(element, data, datalen) \ +@@ -2793,7 +2793,7 @@ struct element { + static inline bool for_each_element_completed(const struct element *element, + const void *data, size_t datalen) + { +- return (u8 *)element == (u8 *)data + datalen; ++ return (const u8 *)element == (const u8 *)data + datalen; + } + + #endif /* LINUX_IEEE80211_H */ diff --git a/queue-4.14/nl80211-validate-beacon-head.patch b/queue-4.14/nl80211-validate-beacon-head.patch new file mode 100644 index 00000000000..6c8b9868438 --- /dev/null +++ b/queue-4.14/nl80211-validate-beacon-head.patch @@ -0,0 +1,82 @@ +From f88eb7c0d002a67ef31aeb7850b42ff69abc46dc Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 20 Sep 2019 21:54:17 +0200 +Subject: nl80211: validate beacon head + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -199,6 +199,38 @@ cfg80211_get_dev_from_info(struct net *n + 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; ++} ++ + /* policy for the attributes */ + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -3738,6 +3770,12 @@ static int nl80211_parse_beacon(struct n + memset(bcn, 0, sizeof(*bcn)); + + if (attrs[NL80211_ATTR_BEACON_HEAD]) { ++ int ret = validate_beacon_head(attrs[NL80211_ATTR_BEACON_HEAD], ++ NULL); ++ ++ if (ret) ++ return ret; ++ + bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); + bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); + if (!bcn->head_len) diff --git a/queue-4.14/series b/queue-4.14/series index fd3f4e6bc9d..557a38dee03 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -55,3 +55,6 @@ perf-stat-reset-previous-counts-on-repeat-with-inter.patch drm-i915-userptr-acquire-the-page-lock-around-set_pa.patch vfs-fix-eoverflow-testing-in-put_compat_statfs64.patch coresight-etm4x-use-explicit-barriers-on-enable-disable.patch +cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch +cfg80211-use-const-more-consistently-in-for_each_element-macros.patch +nl80211-validate-beacon-head.patch