* [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty()
@ 2024-02-13 14:09 Roman Smirnov
2024-02-13 14:09 ` [PATCH 5.10/5.15 v2 1/1 RESEND] mm/truncate: Replace page_mapped() call in invalidate_inode_page() Roman Smirnov
2024-02-26 6:45 ` [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
0 siblings, 2 replies; 3+ messages in thread
From: Roman Smirnov @ 2024-02-13 14:09 UTC (permalink / raw)
To: stable, Greg Kroah-Hartman
Cc: Roman Smirnov, Matthew Wilcox (Oracle), Andrew Morton,
Alexey Khoroshilov, Sergey Shtylyov, Karina Yankevich,
lvc-project, linux-fsdevel, linux-kernel, linux-mm
Syzkaller reports warning in ext4_set_page_dirty() in 5.10 and 5.15
stable releases. It happens because invalidate_inode_page() frees pages
that are needed for the system. To fix this we need to add additional
checks to the function. page_mapped() checks if a page exists in the
page tables, but this is not enough. The page can be used in other places:
https://elixir.bootlin.com/linux/v6.8-rc1/source/include/linux/page_ref.h#L71
Kernel outputs an error line related to direct I/O:
https://syzkaller.appspot.com/text?tag=CrashLog&x=14ab52dac80000
The problem can be fixed in 5.10 and 5.15 stable releases by the
following patch.
The patch replaces page_mapped() call with check that finds additional
references to the page excluding page cache and filesystem private data.
If additional references exist, the page cannot be freed.
This version does not include the first patch from the first version.
The problem can be fixed without it.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Link: https://syzkaller.appspot.com/bug?extid=02f21431b65c214aa1d6
Previous discussion:
https://lore.kernel.org/all/20240125130947.600632-1-r.smirnov@omp.ru/T/
Matthew Wilcox (Oracle) (1):
mm/truncate: Replace page_mapped() call in invalidate_inode_page()
mm/truncate.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 5.10/5.15 v2 1/1 RESEND] mm/truncate: Replace page_mapped() call in invalidate_inode_page()
2024-02-13 14:09 [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
@ 2024-02-13 14:09 ` Roman Smirnov
2024-02-26 6:45 ` [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
1 sibling, 0 replies; 3+ messages in thread
From: Roman Smirnov @ 2024-02-13 14:09 UTC (permalink / raw)
To: stable, Greg Kroah-Hartman
Cc: Roman Smirnov, Matthew Wilcox (Oracle), Andrew Morton,
Alexey Khoroshilov, Sergey Shtylyov, Karina Yankevich,
lvc-project, linux-fsdevel, linux-kernel, linux-mm, Miaohe Lin
From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
commit e41c81d0d30e1a6ebf408feaf561f80cac4457dc upstream.
folio_mapped() is expensive because it has to check each page's mapcount
field. A cheaper check is whether there are any extra references to
the page, other than the one we own, one from the page private data and
the ones held by the page cache.
The call to remove_mapping() will fail in any case if it cannot freeze
the refcount, but failing here avoids cycling the i_pages spinlock.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Miaohe Lin <linmiaohe@huawei.com>
[Roman: replaced folio_ref_count() call with page_ref_count(),
folio_nr_pages() call with compound_nr(), and
folio_has_private() call with page_has_private()]
Signed-off-by: Roman Smirnov <r.smirnov@omp.ru>
---
mm/truncate.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/mm/truncate.c b/mm/truncate.c
index 8914ca4ce4b1..989bc7785d55 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -256,7 +256,9 @@ int invalidate_inode_page(struct page *page)
return 0;
if (PageDirty(page) || PageWriteback(page))
return 0;
- if (page_mapped(page))
+ /* The refcount will be elevated if the page is used by the system */
+ if (page_ref_count(page) >
+ compound_nr(page) + page_has_private(page) + 1)
return 0;
return invalidate_complete_page(mapping, page);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty()
2024-02-13 14:09 [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
2024-02-13 14:09 ` [PATCH 5.10/5.15 v2 1/1 RESEND] mm/truncate: Replace page_mapped() call in invalidate_inode_page() Roman Smirnov
@ 2024-02-26 6:45 ` Roman Smirnov
1 sibling, 0 replies; 3+ messages in thread
From: Roman Smirnov @ 2024-02-26 6:45 UTC (permalink / raw)
To: stable@vger.kernel.org, Greg Kroah-Hartman
Cc: Matthew Wilcox (Oracle), Andrew Morton, Alexey Khoroshilov,
Sergey Shtylyov, Karina Yankevich, lvc-project@linuxtesting.org,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org
On Tue, 13 Feb, 2024 14:09:33 +0000, Roman Smirnov wrote:
> Syzkaller reports warning in ext4_set_page_dirty() in 5.10 and 5.15
> stable releases. It happens because invalidate_inode_page() frees pages
> that are needed for the system. To fix this we need to add additional
> checks to the function. page_mapped() checks if a page exists in the
> page tables, but this is not enough. The page can be used in other places:
> https://elixir.bootlin.com/linux/v6.8-rc1/source/include/linux/page_ref.h#L71
>
> Kernel outputs an error line related to direct I/O:
> https://syzkaller.appspot.com/text?tag=CrashLog&x=14ab52dac80000
>
> The problem can be fixed in 5.10 and 5.15 stable releases by the
> following patch.
>
> The patch replaces page_mapped() call with check that finds additional
> references to the page excluding page cache and filesystem private data.
> If additional references exist, the page cannot be freed.
>
> This version does not include the first patch from the first version.
> The problem can be fixed without it.
>
> Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
>
> Link: https://syzkaller.appspot.com/bug?extid=02f21431b65c214aa1d6
>
> Previous discussion:
> https://lore.kernel.org/all/20240125130947.600632-1-r.smirnov@omp.ru/T/
>
> Matthew Wilcox (Oracle) (1):
> mm/truncate: Replace page_mapped() call in invalidate_inode_page()
>
> mm/truncate.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
Hello.
Sorry to bother you, do you have any comments on the patch?
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-02-26 6:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-13 14:09 [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
2024-02-13 14:09 ` [PATCH 5.10/5.15 v2 1/1 RESEND] mm/truncate: Replace page_mapped() call in invalidate_inode_page() Roman Smirnov
2024-02-26 6:45 ` [PATCH 5.10/5.15 v2 0/1 RESEND] mm/truncate: fix WARNING in ext4_set_page_dirty() Roman Smirnov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).