rq->out[1] should be valid before accessing. Otherwise,
in very rare cases, out-of-bound dirty onstack rq->out[1]
can equal to *in and lead to unintended memmove behavior.

Fixes: 7fc45dbc938a ("staging: erofs: introduce generic decompression backend")
Cc: <[email protected]> # v5.3+
Signed-off-by: Gao Xiang <[email protected]>
---
 fs/erofs/decompressor.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
index 2890a67a1ded..5779a15c2cd6 100644
--- a/fs/erofs/decompressor.c
+++ b/fs/erofs/decompressor.c
@@ -306,24 +306,22 @@ static int z_erofs_shifted_transform(const struct 
z_erofs_decompress_req *rq,
        }
 
        src = kmap_atomic(*rq->in);
-       if (!rq->out[0]) {
-               dst = NULL;
-       } else {
+       if (rq->out[0]) {
                dst = kmap_atomic(rq->out[0]);
                memcpy(dst + rq->pageofs_out, src, righthalf);
+               kunmap_atomic(dst);
        }
 
-       if (rq->out[1] == *rq->in) {
-               memmove(src, src + righthalf, rq->pageofs_out);
-       } else if (nrpages_out == 2) {
-               if (dst)
-                       kunmap_atomic(dst);
+       if (nrpages_out == 2) {
                DBG_BUGON(!rq->out[1]);
-               dst = kmap_atomic(rq->out[1]);
-               memcpy(dst, src + righthalf, rq->pageofs_out);
+               if (rq->out[1] == *rq->in) {
+                       memmove(src, src + righthalf, rq->pageofs_out);
+               } else {
+                       dst = kmap_atomic(rq->out[1]);
+                       memcpy(dst, src + righthalf, rq->pageofs_out);
+                       kunmap_atomic(dst);
+               }
        }
-       if (dst)
-               kunmap_atomic(dst);
        kunmap_atomic(src);
        return 0;
 }
-- 
2.17.1

Reply via email to