Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0236040f authored by Gao Xiang's avatar Gao Xiang Committed by Sasha Levin
Browse files

erofs: fix partially uninitialized misuse in z_erofs_onlinepage_fixup



commit 3c597282887fd55181578996dca52ce697d985a5 upstream.

Hongyu reported "id != index" in z_erofs_onlinepage_fixup() with
specific aarch64 environment easily, which wasn't shown before.

After digging into that, I found that high 32 bits of page->private
was set to 0xaaaaaaaa rather than 0 (due to z_erofs_onlinepage_init
behavior with specific compiler options). Actually we only use low
32 bits to keep the page information since page->private is only 4
bytes on most 32-bit platforms. However z_erofs_onlinepage_fixup()
uses the upper 32 bits by mistake.

Let's fix it now.

Reported-and-tested-by: default avatarHongyu Jin <hongyu.jin@unisoc.com>
Fixes: 3883a79a ("staging: erofs: introduce VLE decompression support")
Cc: <stable@vger.kernel.org> # 4.19+
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Link: https://lore.kernel.org/r/20200618234349.22553-1-hsiangkao@aol.com


Signed-off-by: default avatarGao Xiang <hsiangkao@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 824d0b62
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -148,22 +148,22 @@ static inline void z_erofs_onlinepage_init(struct page *page)
static inline void z_erofs_onlinepage_fixup(struct page *page,
	uintptr_t index, bool down)
{
	unsigned long *p, o, v, id;
repeat:
	p = &page_private(page);
	o = READ_ONCE(*p);
	union z_erofs_onlinepage_converter u = { .v = &page_private(page) };
	int orig, orig_index, val;

	id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
	if (id) {
repeat:
	orig = atomic_read(u.o);
	orig_index = orig >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
	if (orig_index) {
		if (!index)
			return;

		DBG_BUGON(id != index);
		DBG_BUGON(orig_index != index);
	}

	v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
		((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
	if (cmpxchg(p, o, v) != o)
	val = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
		((orig & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
	if (atomic_cmpxchg(u.o, orig, val) != orig)
		goto repeat;
}