]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
erofs: fix out-of-bound read for shifted uncompressed block
authorGao Xiang <gaoxiang25@huawei.com>
Tue, 7 Jan 2020 02:25:46 +0000 (10:25 +0800)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 13 Mar 2020 05:26:35 +0000 (01:26 -0400)
BugLink: https://bugs.launchpad.net/bugs/1867051
commit 4d2024370d877f9ac8b98694bcff666da6a5d333 upstream.

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.

Link: https://lore.kernel.org/r/20200107022546.19432-1-gaoxiang25@huawei.com
Fixes: 7fc45dbc938a ("staging: erofs: introduce generic decompression backend")
Cc: <stable@vger.kernel.org> # 5.3+
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/staging/erofs/decompressor.c

index 1fb0abb98dffdd716775e14d6b2c0b4c8ed998db..0dbd7799c627a32ed510d662d62f1ba7d81e8248 100644 (file)
@@ -303,24 +303,22 @@ static int shifted_decompress(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;
 }