Commit 2690c88d authored by Jakob Koschel's avatar Jakob Koschel Committed by Wupeng Ma
Browse files

f2fs: fix dereference of stale list iterator after loop body

stable inclusion
from stable-v4.19.247
commit 385edd3ce5b4b1e9d31f474a5e35a39779ec1110
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBP3SH
CVE: CVE-2022-49425

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=385edd3ce5b4b1e9d31f474a5e35a39779ec1110



--------------------------------

[ Upstream commit 2aaf51dd ]

The list iterator variable will be a bogus pointer if no break was hit.
Dereferencing it (cur->page in this case) could load an out-of-bounds/undefined
value making it unsafe to use that in the comparision to determine if the
specific element was found.

Since 'cur->page' *can* be out-ouf-bounds it cannot be guaranteed that
by chance (or intention of an attacker) it matches the value of 'page'
even though the correct element was not found.

This is fixed by using a separate list iterator variable for the loop
and only setting the original variable if a suitable element was found.
Then determing if the element was found is simply checking if the
variable is set.

Fixes: 8c242db9 ("f2fs: fix stale ATOMIC_WRITTEN_PAGE private pointer")
Signed-off-by: default avatarJakob Koschel <jakobkoschel@gmail.com>
Reviewed-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWupeng Ma <mawupeng1@huawei.com>
parent 5b56c883
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -354,16 +354,19 @@ void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
	struct list_head *head = &fi->inmem_pages;
	struct inmem_pages *cur = NULL;
	struct inmem_pages *tmp;

	f2fs_bug_on(sbi, !IS_ATOMIC_WRITTEN_PAGE(page));

	mutex_lock(&fi->inmem_lock);
	list_for_each_entry(cur, head, list) {
		if (cur->page == page)
	list_for_each_entry(tmp, head, list) {
		if (tmp->page == page) {
			cur = tmp;
			break;
		}
	}

	f2fs_bug_on(sbi, list_empty(head) || cur->page != page);
	f2fs_bug_on(sbi, !cur);
	list_del(&cur->list);
	mutex_unlock(&fi->inmem_lock);