--- /dev/null
+From 0f3b07f027f87a38ebe5c436490095df762819be Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 7 Feb 2019 21:44:41 +0100
+Subject: cfg80211: add and use strongly typed element iteration macros
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+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 <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -3185,4 +3185,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;
--- /dev/null
+From 7388afe09143210f555bdd6c75035e9acc1fab96 Mon Sep 17 00:00:00 2001
+From: Jouni Malinen <j@w1.fi>
+Date: Mon, 11 Feb 2019 16:29:04 +0200
+Subject: cfg80211: Use const more consistently in for_each_element macros
+
+From: Jouni Malinen <j@w1.fi>
+
+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 <j@w1.fi>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/ieee80211.h | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -3189,16 +3189,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) \
+@@ -3235,7 +3235,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 */
--- /dev/null
+From f88eb7c0d002a67ef31aeb7850b42ff69abc46dc Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Fri, 20 Sep 2019 21:54:17 +0200
+Subject: nl80211: validate beacon head
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/wireless/nl80211.c | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -200,6 +200,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 },
+@@ -4016,6 +4048,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)
arm64-speculation-support-mitigations-cmdline-option.patch
vfs-fix-eoverflow-testing-in-put_compat_statfs64.patch
coresight-etm4x-use-explicit-barriers-on-enable-disable.patch
+staging-erofs-fix-an-error-handling-in-erofs_readdir.patch
+staging-erofs-some-compressed-cluster-should-be-submitted-for-corrupted-images.patch
+staging-erofs-add-two-missing-erofs_workgroup_put-for-corrupted-images.patch
+staging-erofs-detect-potential-multiref-due-to-corrupted-images.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
--- /dev/null
+From foo@baz Wed 09 Oct 2019 03:26:06 PM CEST
+From: Gao Xiang <gaoxiang25@huawei.com>
+Date: Wed, 9 Oct 2019 18:12:38 +0800
+Subject: staging: erofs: add two missing erofs_workgroup_put for corrupted images
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, <stable@vger.kernel.org>, Chao Yu <yuchao0@huawei.com>
+Cc: <linux-erofs@lists.ozlabs.org>, Miao Xie <miaoxie@huawei.com>, Gao Xiang <gaoxiang25@huawei.com>
+Message-ID: <20191009101239.195587-3-gaoxiang25@huawei.com>
+
+From: Gao Xiang <gaoxiang25@huawei.com>
+
+commit 138e1a0990e80db486ab9f6c06bd5c01f9a97999 upstream.
+
+As reported by erofs-utils fuzzer, these error handling
+path will be entered to handle corrupted images.
+
+Lack of erofs_workgroup_puts will cause unmounting
+unsuccessfully.
+
+Fix these return values to EFSCORRUPTED as well.
+
+Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support")
+Cc: <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Link: https://lore.kernel.org/r/20190819103426.87579-4-gaoxiang25@huawei.com
+[ Gao Xiang: Older kernel versions don't have length validity check
+ and EFSCORRUPTED, thus backport pageofs check for now. ]
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/erofs/unzip_vle.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/staging/erofs/unzip_vle.c
++++ b/drivers/staging/erofs/unzip_vle.c
+@@ -311,7 +311,11 @@ z_erofs_vle_work_lookup(struct super_blo
+ /* if multiref is disabled, `primary' is always true */
+ primary = true;
+
+- DBG_BUGON(work->pageofs != pageofs);
++ if (work->pageofs != pageofs) {
++ DBG_BUGON(1);
++ erofs_workgroup_put(egrp);
++ return ERR_PTR(-EIO);
++ }
+
+ /*
+ * lock must be taken first to avoid grp->next == NIL between
--- /dev/null
+From foo@baz Wed 09 Oct 2019 03:26:06 PM CEST
+From: Gao Xiang <gaoxiang25@huawei.com>
+Date: Wed, 9 Oct 2019 18:12:39 +0800
+Subject: staging: erofs: detect potential multiref due to corrupted images
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, <stable@vger.kernel.org>, Chao Yu <yuchao0@huawei.com>
+Cc: <linux-erofs@lists.ozlabs.org>, Miao Xie <miaoxie@huawei.com>, Gao Xiang <gaoxiang25@huawei.com>
+Message-ID: <20191009101239.195587-4-gaoxiang25@huawei.com>
+
+From: Gao Xiang <gaoxiang25@huawei.com>
+
+commit e12a0ce2fa69798194f3a8628baf6edfbd5c548f upstream.
+
+As reported by erofs-utils fuzzer, currently, multiref
+(ondisk deduplication) hasn't been supported for now,
+we should forbid it properly.
+
+Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support")
+Cc: <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Link: https://lore.kernel.org/r/20190821140152.229648-1-gaoxiang25@huawei.com
+[ Gao Xiang: Since earlier kernels don't define EFSCORRUPTED,
+ let's use EIO instead. ]
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/erofs/unzip_vle.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/staging/erofs/unzip_vle.c
++++ b/drivers/staging/erofs/unzip_vle.c
+@@ -857,6 +857,7 @@ repeat:
+ for (i = 0; i < nr_pages; ++i)
+ pages[i] = NULL;
+
++ err = 0;
+ z_erofs_pagevec_ctor_init(&ctor,
+ Z_EROFS_VLE_INLINE_PAGEVECS, work->pagevec, 0);
+
+@@ -878,8 +879,17 @@ repeat:
+ pagenr = z_erofs_onlinepage_index(page);
+
+ DBG_BUGON(pagenr >= nr_pages);
+- DBG_BUGON(pages[pagenr]);
+
++ /*
++ * currently EROFS doesn't support multiref(dedup),
++ * so here erroring out one multiref page.
++ */
++ if (pages[pagenr]) {
++ DBG_BUGON(1);
++ SetPageError(pages[pagenr]);
++ z_erofs_onlinepage_endio(pages[pagenr]);
++ err = -EIO;
++ }
+ pages[pagenr] = page;
+ }
+ sparsemem_pages = i;
+@@ -889,7 +899,6 @@ repeat:
+ overlapped = false;
+ compressed_pages = grp->compressed_pages;
+
+- err = 0;
+ for (i = 0; i < clusterpages; ++i) {
+ unsigned pagenr;
+
+@@ -915,7 +924,12 @@ repeat:
+ pagenr = z_erofs_onlinepage_index(page);
+
+ DBG_BUGON(pagenr >= nr_pages);
+- DBG_BUGON(pages[pagenr]);
++ if (pages[pagenr]) {
++ DBG_BUGON(1);
++ SetPageError(pages[pagenr]);
++ z_erofs_onlinepage_endio(pages[pagenr]);
++ err = -EIO;
++ }
+ ++sparsemem_pages;
+ pages[pagenr] = page;
+
--- /dev/null
+From foo@baz Wed 09 Oct 2019 03:26:06 PM CEST
+From: Gao Xiang <gaoxiang25@huawei.com>
+Date: Wed, 9 Oct 2019 18:12:36 +0800
+Subject: staging: erofs: fix an error handling in erofs_readdir()
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, <stable@vger.kernel.org>, Chao Yu <yuchao0@huawei.com>
+Cc: <linux-erofs@lists.ozlabs.org>, Miao Xie <miaoxie@huawei.com>, Gao Xiang <gaoxiang25@huawei.com>
+Message-ID: <20191009101239.195587-1-gaoxiang25@huawei.com>
+
+From: Gao Xiang <gaoxiang25@huawei.com>
+
+commit acb383f1dcb4f1e79b66d4be3a0b6f519a957b0d upstream.
+
+Richard observed a forever loop of erofs_read_raw_page() [1]
+which can be generated by forcely setting ->u.i_blkaddr
+to 0xdeadbeef (as my understanding block layer can
+handle access beyond end of device correctly).
+
+After digging into that, it seems the problem is highly
+related with directories and then I found the root cause
+is an improper error handling in erofs_readdir().
+
+Let's fix it now.
+
+[1] https://lore.kernel.org/r/1163995781.68824.1566084358245.JavaMail.zimbra@nod.at/
+
+Reported-by: Richard Weinberger <richard@nod.at>
+Fixes: 3aa8ec716e52 ("staging: erofs: add directory operations")
+Cc: <stable@vger.kernel.org> # 4.19+
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Link: https://lore.kernel.org/r/20190818125457.25906-1-hsiangkao@aol.com
+[ Gao Xiang: Since earlier kernels don't define EFSCORRUPTED,
+ let's use original error code instead. ]
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/erofs/dir.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/staging/erofs/dir.c
++++ b/drivers/staging/erofs/dir.c
+@@ -100,8 +100,15 @@ static int erofs_readdir(struct file *f,
+ unsigned nameoff, maxsize;
+
+ dentry_page = read_mapping_page(mapping, i, NULL);
+- if (IS_ERR(dentry_page))
+- continue;
++ if (dentry_page == ERR_PTR(-ENOMEM)) {
++ err = -ENOMEM;
++ break;
++ } else if (IS_ERR(dentry_page)) {
++ errln("fail to readdir of logical block %u of nid %llu",
++ i, EROFS_V(dir)->nid);
++ err = PTR_ERR(dentry_page);
++ break;
++ }
+
+ lock_page(dentry_page);
+ de = (struct erofs_dirent *)kmap(dentry_page);
--- /dev/null
+From foo@baz Wed 09 Oct 2019 03:26:06 PM CEST
+From: Gao Xiang <gaoxiang25@huawei.com>
+Date: Wed, 9 Oct 2019 18:12:37 +0800
+Subject: staging: erofs: some compressed cluster should be submitted for corrupted images
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, <stable@vger.kernel.org>, Chao Yu <yuchao0@huawei.com>
+Cc: <linux-erofs@lists.ozlabs.org>, Miao Xie <miaoxie@huawei.com>, Gao Xiang <gaoxiang25@huawei.com>
+Message-ID: <20191009101239.195587-2-gaoxiang25@huawei.com>
+
+From: Gao Xiang <gaoxiang25@huawei.com>
+
+commit ee45197c807895e156b2be0abcaebdfc116487c8 upstream.
+
+As reported by erofs_utils fuzzer, a logical page can belong
+to at most 2 compressed clusters, if one compressed cluster
+is corrupted, but the other has been ready in submitting chain.
+
+The chain needs to submit anyway in order to keep the page
+working properly (page unlocked with PG_error set, PG_uptodate
+not set).
+
+Let's fix it now.
+
+Fixes: 3883a79abd02 ("staging: erofs: introduce VLE decompression support")
+Cc: <stable@vger.kernel.org> # 4.19+
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Link: https://lore.kernel.org/r/20190819103426.87579-2-gaoxiang25@huawei.com
+[ Gao Xiang: Manually backport to v4.19.y stable. ]
+Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/erofs/unzip_vle.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/staging/erofs/unzip_vle.c
++++ b/drivers/staging/erofs/unzip_vle.c
+@@ -1335,19 +1335,18 @@ static int z_erofs_vle_normalaccess_read
+ err = z_erofs_do_read_page(&f, page, &pagepool);
+ (void)z_erofs_vle_work_iter_end(&f.builder);
+
+- if (err) {
++ /* if some compressed cluster ready, need submit them anyway */
++ z_erofs_submit_and_unzip(&f, &pagepool, true);
++
++ if (err)
+ errln("%s, failed to read, err [%d]", __func__, err);
+- goto out;
+- }
+
+- z_erofs_submit_and_unzip(&f, &pagepool, true);
+-out:
+ if (f.m_iter.mpage != NULL)
+ put_page(f.m_iter.mpage);
+
+ /* clean up the remaining free pages */
+ put_pages_list(&pagepool);
+- return 0;
++ return err;
+ }
+
+ static inline int __z_erofs_vle_normalaccess_readpages(