From: Greg Kroah-Hartman Date: Wed, 9 Oct 2019 13:40:05 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.14.149~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ae36f5f2c41ac340cfb564d30e307d8b0e8ef0e2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-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.4/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch b/queue-4.4/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch new file mode 100644 index 00000000000..9d4b3121097 --- /dev/null +++ b/queue-4.4/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch @@ -0,0 +1,103 @@ +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 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2550,4 +2550,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 */ diff --git a/queue-4.4/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch b/queue-4.4/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch new file mode 100644 index 00000000000..bed6d1ff252 --- /dev/null +++ b/queue-4.4/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 +@@ -2554,16 +2554,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) \ +@@ -2600,7 +2600,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.4/nl80211-validate-beacon-head.patch b/queue-4.4/nl80211-validate-beacon-head.patch new file mode 100644 index 00000000000..3bb1d0c2bf9 --- /dev/null +++ b/queue-4.4/nl80211-validate-beacon-head.patch @@ -0,0 +1,79 @@ +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 | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -210,6 +210,36 @@ 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) ++{ ++ 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 */ + static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -3214,6 +3244,11 @@ 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]); ++ ++ 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.4/series b/queue-4.4/series index ec197e7c333..60f30d871ce 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -24,3 +24,6 @@ perf-stat-fix-a-segmentation-fault-when-using-repeat.patch perf-stat-reset-previous-counts-on-repeat-with-inter.patch drm-i915-userptr-acquire-the-page-lock-around-set_pa.patch crypto-caam-fix-concurrency-issue-in-givencrypt-descriptor.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