erofs: fix out-of-bound read for shifted uncompressed block

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: 7fc45dbc93 ("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>
This commit is contained in:
Gao Xiang 2020-01-07 10:25:46 +08:00
parent e3915ad94b
commit 4d2024370d
1 changed files with 10 additions and 12 deletions

View File

@ -306,24 +306,22 @@ static int z_erofs_shifted_transform(const struct z_erofs_decompress_req *rq,
} }
src = kmap_atomic(*rq->in); src = kmap_atomic(*rq->in);
if (!rq->out[0]) { if (rq->out[0]) {
dst = NULL;
} else {
dst = kmap_atomic(rq->out[0]); dst = kmap_atomic(rq->out[0]);
memcpy(dst + rq->pageofs_out, src, righthalf); memcpy(dst + rq->pageofs_out, src, righthalf);
kunmap_atomic(dst);
} }
if (rq->out[1] == *rq->in) { if (nrpages_out == 2) {
memmove(src, src + righthalf, rq->pageofs_out);
} else if (nrpages_out == 2) {
if (dst)
kunmap_atomic(dst);
DBG_BUGON(!rq->out[1]); DBG_BUGON(!rq->out[1]);
dst = kmap_atomic(rq->out[1]); if (rq->out[1] == *rq->in) {
memcpy(dst, src + righthalf, rq->pageofs_out); 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); kunmap_atomic(src);
return 0; return 0;
} }