]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Oct 2019 13:36:20 +0000 (15:36 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Oct 2019 13:36:20 +0000 (15:36 +0200)
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
staging-erofs-add-two-missing-erofs_workgroup_put-for-corrupted-images.patch
staging-erofs-detect-potential-multiref-due-to-corrupted-images.patch
staging-erofs-fix-an-error-handling-in-erofs_readdir.patch
staging-erofs-some-compressed-cluster-should-be-submitted-for-corrupted-images.patch

queue-4.19/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch [new file with mode: 0644]
queue-4.19/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch [new file with mode: 0644]
queue-4.19/nl80211-validate-beacon-head.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/staging-erofs-add-two-missing-erofs_workgroup_put-for-corrupted-images.patch [new file with mode: 0644]
queue-4.19/staging-erofs-detect-potential-multiref-due-to-corrupted-images.patch [new file with mode: 0644]
queue-4.19/staging-erofs-fix-an-error-handling-in-erofs_readdir.patch [new file with mode: 0644]
queue-4.19/staging-erofs-some-compressed-cluster-should-be-submitted-for-corrupted-images.patch [new file with mode: 0644]

diff --git a/queue-4.19/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch b/queue-4.19/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch
new file mode 100644 (file)
index 0000000..c018580
--- /dev/null
@@ -0,0 +1,134 @@
+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;
diff --git a/queue-4.19/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch b/queue-4.19/cfg80211-use-const-more-consistently-in-for_each_element-macros.patch
new file mode 100644 (file)
index 0000000..c1ec7c7
--- /dev/null
@@ -0,0 +1,59 @@
+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 */
diff --git a/queue-4.19/nl80211-validate-beacon-head.patch b/queue-4.19/nl80211-validate-beacon-head.patch
new file mode 100644 (file)
index 0000000..b7c2985
--- /dev/null
@@ -0,0 +1,82 @@
+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)
index fd265c98536ad624f8b9add474f5d036c20e6394..8669e943057c638534a8bfa9f7abbca3a16310c5 100644 (file)
@@ -105,3 +105,10 @@ arm64-use-firmware-to-detect-cpus-that-are-not-affected-by-spectre-v2.patch
 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
diff --git a/queue-4.19/staging-erofs-add-two-missing-erofs_workgroup_put-for-corrupted-images.patch b/queue-4.19/staging-erofs-add-two-missing-erofs_workgroup_put-for-corrupted-images.patch
new file mode 100644 (file)
index 0000000..e3ae687
--- /dev/null
@@ -0,0 +1,48 @@
+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
diff --git a/queue-4.19/staging-erofs-detect-potential-multiref-due-to-corrupted-images.patch b/queue-4.19/staging-erofs-detect-potential-multiref-due-to-corrupted-images.patch
new file mode 100644 (file)
index 0000000..4a390ac
--- /dev/null
@@ -0,0 +1,80 @@
+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;
diff --git a/queue-4.19/staging-erofs-fix-an-error-handling-in-erofs_readdir.patch b/queue-4.19/staging-erofs-fix-an-error-handling-in-erofs_readdir.patch
new file mode 100644 (file)
index 0000000..36ec1ed
--- /dev/null
@@ -0,0 +1,59 @@
+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);
diff --git a/queue-4.19/staging-erofs-some-compressed-cluster-should-be-submitted-for-corrupted-images.patch b/queue-4.19/staging-erofs-some-compressed-cluster-should-be-submitted-for-corrupted-images.patch
new file mode 100644 (file)
index 0000000..10a5f76
--- /dev/null
@@ -0,0 +1,61 @@
+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(