From: Aleksandr Panfilenko <lexpasss@inbox.lv>
To: linux-ext4@vger.kernel.org
Cc: tytso@mit.edu, adilger@dilger.ca, willy@infradead.org,
stable@vger.kernel.org, linux-kernel@vger.kernel.org,
Aleksandr Panfilenko <lexpasss@inbox.lv>
Subject: [PATCH 1/1] ext4: fix NULL pointer dereference in ext4_mb_load_buddy_gfp()
Date: Tue, 10 Nov 2026 22:37:11 +0300 [thread overview]
Message-ID: <20261110193711.3106773-2-lexpasss@inbox.lv> (raw)
In-Reply-To: <20261110193711.3106773-1-lexpasss@inbox.lv>
__filemap_get_folio() called without FGP_CREAT returns NULL, not an error
pointer, when the folio is not present in the page cache. The fast path
in ext4_mb_load_buddy_gfp() only checks IS_ERR(folio) before evaluating
folio_test_uptodate(folio), so a NULL return leads to a NULL pointer
dereference in the folio flags test.
The buddy cache folios can in fact disappear from the page cache: they
are clean pages of the s_buddy_cache inode and can be reclaimed under
memory pressure, while nothing sets EXT4_MB_GRP_NEED_INIT again, so
ext4_mb_init_group() is not called to reload them. We have hit this
twice in one day on 6.1.192 during background writeback on a server
under heavy page cache churn (fresh OS install + database restore):
BUG: kernel NULL pointer dereference, address: 0000000000000000
Oops: 0000 [#1] PREEMPT SMP NOPTI
CPU: 51 PID: 137989 Comm: kworker/u161:1 Kdump: loaded
Workqueue: writeback wb_workfn (flush-253:1)
RIP: 0010:ext4_mb_load_buddy_gfp+0xc0/0x3a0 [ext4]
Code: ... 48 3d 00 f0 ff ff 0f 87 ... <48> 8b 00 a8 04 ...
RAX: 0000000000000000
Call Trace:
ext4_mb_regular_allocator+0x1ba/0x600 [ext4]
ext4_mb_new_blocks+0x3a9/0x530 [ext4]
ext4_ext_map_blocks+0x670/0x8a0 [ext4]
ext4_map_blocks+0x22b/0x5d0 [ext4]
mpage_map_one_extent+0x60/0x170 [ext4]
mpage_map_and_submit_extent+0x76/0x300 [ext4]
ext4_writepages+0x6f8/0x860 [ext4]
...
The faulting instruction is the folio flags load (mov rax,[rax] with
RAX == 0) between the IS_ERR() check and the PG_uptodate test.
Before the folio conversion this was handled correctly: the old code used
find_get_page_flags() and explicitly tested "page == NULL" first, in both
the bitmap lookup (converted by 99b150d84e49) and the buddy lookup
(converted by 5eea586b47f0). Treat a NULL folio the same way as the
"not uptodate / locked" cases and fall back to the FGP_CREAT path, which
will re-create the folio. Also switch the two folio_put() guards to
!IS_ERR_OR_NULL() so that we do not call folio_put(NULL) after taking
the slow path with a NULL folio.
The error-path fix in c6a6c9694aad ("ext4: fix error pointer dereference
in ext4_mb_load_buddy_gfp()") does not cover this case.
The bug reproduces deterministically on 6.1.192: loop-mount a fresh
ext4 filesystem, write ~200 MB of files, sync, then run
"echo 3 > /proc/sys/vm/drop_caches" and write more files. The drop
evicts the buddy cache folios, and the next allocation in the writeback
worker hits the NULL fast path within seconds:
RIP: 0010:ext4_mb_load_buddy_gfp+0xc0/0x3a0 [ext4]
Workqueue: writeback wb_workfn (flush-7:0)
RAX: 0000000000000000
Call Trace:
ext4_mb_regular_allocator+0x1ba/0x600 [ext4]
ext4_mb_new_blocks+0x3a9/0x530 [ext4]
...
With this patch applied (the ext4 module rebuilt against the same
kernel and config), the same sequence completes cleanly over multiple
cycles, with no oops and no ext4 warnings in dmesg.
Fixes: 99b150d84e49 ("ext4: convert bd_bitmap_page to bd_bitmap_folio")
Fixes: 5eea586b47f0 ("ext4: convert bd_buddy_page to bd_buddy_folio")
Cc: stable@vger.kernel.org
Reported-by: Aleksandr Panfilenko <lexpasss@inbox.lv>
Signed-off-by: Aleksandr Panfilenko <lexpasss@inbox.lv>
---
fs/ext4/mballoc.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a15285224..11ca5a148 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1715,7 +1715,8 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
/* Avoid locking the folio in the fast path ... */
folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
- if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) {
+ if (IS_ERR_OR_NULL(folio) || !folio_test_uptodate(folio) ||
+ folio_test_locked(folio)) {
/*
* folio_test_locked is employed to detect ongoing folio
* migrations, since concurrent migrations can lead to
@@ -1725,7 +1726,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
* try to get the folio with lock in both cases to avoid
* concurrency.
*/
- if (!IS_ERR(folio))
+ if (!IS_ERR_OR_NULL(folio))
folio_put(folio);
folio = __filemap_get_folio(inode->i_mapping, pnum,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
@@ -1774,8 +1775,9 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
/* we need another folio for the buddy */
folio = __filemap_get_folio(inode->i_mapping, pnum, FGP_ACCESSED, 0);
- if (IS_ERR(folio) || !folio_test_uptodate(folio) || folio_test_locked(folio)) {
- if (!IS_ERR(folio))
+ if (IS_ERR_OR_NULL(folio) || !folio_test_uptodate(folio) ||
+ folio_test_locked(folio)) {
+ if (!IS_ERR_OR_NULL(folio))
folio_put(folio);
folio = __filemap_get_folio(inode->i_mapping, pnum,
FGP_LOCK | FGP_ACCESSED | FGP_CREAT, gfp);
--
2.34.1
next prev parent reply other threads:[~2026-11-10 19:37 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 19:37 [PATCH 0/1] " Aleksandr Panfilenko
2026-11-10 19:37 ` Aleksandr Panfilenko [this message]
2026-11-10 19:44 ` Matthew Wilcox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110193711.3106773-2-lexpasss@inbox.lv \
--to=lexpasss@inbox.lv \
--cc=adilger@dilger.ca \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®