mirror of https://gitee.com/openkylin/linux.git
erofs: fix partially uninitialized misuse in z_erofs_onlinepage_fixup
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: Hongyu Jin <hongyu.jin@unisoc.com>
Fixes: 3883a79abd
("staging: erofs: introduce VLE decompression support")
Cc: <stable@vger.kernel.org> # 4.19+
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Link: https://lore.kernel.org/r/20200618234349.22553-1-hsiangkao@aol.com
Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
This commit is contained in:
parent
b3a9e3b962
commit
3c59728288
|
@ -144,22 +144,22 @@ static inline void z_erofs_onlinepage_init(struct page *page)
|
||||||
static inline void z_erofs_onlinepage_fixup(struct page *page,
|
static inline void z_erofs_onlinepage_fixup(struct page *page,
|
||||||
uintptr_t index, bool down)
|
uintptr_t index, bool down)
|
||||||
{
|
{
|
||||||
unsigned long *p, o, v, id;
|
union z_erofs_onlinepage_converter u = { .v = &page_private(page) };
|
||||||
repeat:
|
int orig, orig_index, val;
|
||||||
p = &page_private(page);
|
|
||||||
o = READ_ONCE(*p);
|
|
||||||
|
|
||||||
id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
|
repeat:
|
||||||
if (id) {
|
orig = atomic_read(u.o);
|
||||||
|
orig_index = orig >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
|
||||||
|
if (orig_index) {
|
||||||
if (!index)
|
if (!index)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DBG_BUGON(id != index);
|
DBG_BUGON(orig_index != index);
|
||||||
}
|
}
|
||||||
|
|
||||||
v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
|
val = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
|
||||||
((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
|
((orig & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
|
||||||
if (cmpxchg(p, o, v) != o)
|
if (atomic_cmpxchg(u.o, orig, val) != orig)
|
||||||
goto repeat;
|
goto repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue