[syzbot] [ext4?] WARNING in __folio_mark_dirty (3)

14 views
Skip to first unread message

syzbot

unread,
Nov 20, 2025, 11:41:33 AMNov 20
to ak...@linux-foundation.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com, wi...@infradead.org
Hello,

syzbot found the following issue on:

HEAD commit: 23cb64fb7625 Merge tag 'soc-fixes-6.18-3' of git://git.ker..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1287997c580000
kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=172cd658580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15378484580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/a14ebce6c664/disk-23cb64fb.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/7703c3032e2f/vmlinux-23cb64fb.xz
kernel image: https://storage.googleapis.com/syzbot-assets/a16c5b94924d/bzImage-23cb64fb.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/4fa9525269b6/mount_0.gz
fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=11d42a12580000)

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com

EXT4-fs error (device loop0): ext4_ext_remove_space:2955: inode #15: comm syz.0.51: pblk 0 bad header/extent: invalid extent entries - magic f30a, entries 2, max 4(4), depth 0(0)
EXT4-fs error (device loop0) in ext4_setattr:6050: Corrupt filesystem
EXT4-fs error (device loop0): ext4_validate_block_bitmap:441: comm syz.0.51: bg 0: block 112: padding at end of block bitmap is not set
EXT4-fs error (device loop0): ext4_map_blocks:778: inode #15: block 3: comm syz.0.51: lblock 3 mapped to illegal pblock 3 (length 1)
EXT4-fs error (device loop0): ext4_ext_remove_space:2955: inode #15: comm syz.0.51: pblk 0 bad header/extent: invalid extent entries - magic f30a, entries 2, max 4(4), depth 0(0)
------------[ cut here ]------------
WARNING: CPU: 0 PID: 6107 at mm/page-writeback.c:2716 __folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Modules linked in:
CPU: 0 UID: 0 PID: 6107 Comm: syz.0.51 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
RIP: 0010:__folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Code: 3c 38 00 74 08 48 89 df e8 52 a7 26 00 4c 8b 33 4c 89 f6 48 83 e6 08 31 ff e8 d1 ed c4 ff 49 83 e6 08 75 1c e8 66 e8 c4 ff 90 <0f> 0b 90 eb 16 e8 5b e8 c4 ff e9 7e 07 00 00 e8 51 e8 c4 ff eb 05
RSP: 0018:ffffc90003a079d0 EFLAGS: 00010293
RAX: ffffffff81f9c4ea RBX: ffffea0001213400 RCX: ffff888025260000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
R10: dffffc0000000000 R11: fffff94000242681 R12: ffff8880416cb4f0
R13: ffff8880416cb4e8 R14: 0000000000000000 R15: dffffc0000000000
FS: 0000555587ebe500(0000) GS:ffff888126df7000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000440 CR3: 000000002e288000 CR4: 00000000003526f0
Call Trace:
<TASK>
block_dirty_folio+0x17a/0x1d0 fs/buffer.c:754
fault_dirty_shared_page+0x103/0x570 mm/memory.c:3519
wp_page_shared mm/memory.c:3906 [inline]
do_wp_page+0x263e/0x4930 mm/memory.c:4109
handle_pte_fault mm/memory.c:6211 [inline]
__handle_mm_fault mm/memory.c:6336 [inline]
handle_mm_fault+0x97c/0x3400 mm/memory.c:6505
do_user_addr_fault+0xa7c/0x1380 arch/x86/mm/fault.c:1336
handle_page_fault arch/x86/mm/fault.c:1476 [inline]
exc_page_fault+0x82/0x100 arch/x86/mm/fault.c:1532
asm_exc_page_fault+0x26/0x30 arch/x86/include/asm/idtentry.h:618
RIP: 0033:0x7f385fe87398
Code: fc 89 37 c3 c5 fa 6f 06 c5 fa 6f 4c 16 f0 c5 fa 7f 07 c5 fa 7f 4c 17 f0 c3 66 0f 1f 84 00 00 00 00 00 48 8b 4c 16 f8 48 8b 36 <48> 89 37 48 89 4c 17 f8 c3 c5 fe 6f 54 16 e0 c5 fe 6f 5c 16 c0 c5
RSP: 002b:00007ffd3b8738f8 EFLAGS: 00010246
RAX: 0000200000000440 RBX: 0000000000000004 RCX: 0030656c69662f2e
RDX: 0000000000000008 RSI: 0030656c69662f2e RDI: 0000200000000440
RBP: 0000000000000000 R08: 0000001b2d820000 R09: 0000000000000001
R10: 0000000000000001 R11: 0000000000000009 R12: 00007f3860115fac
R13: 00007f3860115fa0 R14: fffffffffffffffe R15: 0000000000000004
</TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

syzbot

unread,
Nov 20, 2025, 8:34:53 PMNov 20
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
For archival purposes, forwarding an incoming command email to
linux-...@vger.kernel.org, syzkall...@googlegroups.com.

***

Subject: [PATCH] ext4: check folio uptodate state in ext4_page_mkwrite()
Author: karti...@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


When a write fault occurs on a memory-mapped ext4 file, ext4_page_mkwrite()
is called to prepare the folio for writing. However, if the folio could
not be read successfully due to filesystem corruption or I/O errors, it
will not be marked uptodate.

Attempting to write to a non-uptodate folio is problematic because:
1. We don't have valid data from the backing store to preserve
2. A subsequent writeback could write uninitialized data to disk
3. It triggers a warning in __folio_mark_dirty():
WARN_ON_ONCE(warn && !folio_test_uptodate(folio))

This issue can be reproduced by:
1. Creating a corrupted ext4 filesystem with invalid extent entries
2. Memory-mapping a file on that filesystem
3. Attempting to write to the mapped region

The sequence of events is:
- User reads/writes to mmap region -> page fault
- ext4_filemap_fault() -> ext4_map_blocks() detects corruption
- Returns error, folio allocated but NOT marked uptodate
- User writes to same region -> ext4_page_mkwrite() called
- No uptodate check -> folio marked dirty -> WARNING

Fix this by checking folio_test_uptodate() after locking the folio in
ext4_page_mkwrite(). If the folio is not uptodate, unlock it and return
VM_FAULT_SIGBUS to signal the error to userspace. This is consistent
with how we handle other error conditions like truncated folios.

Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
Signed-off-by: Deepanshu Kartikey <karti...@gmail.com>
---
fs/buffer.c | 5 +++--
fs/ext4/inode.c | 11 ++++++++++-
2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 6a8752f7bbed..805cc0a2ecab 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2621,7 +2621,8 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
unsigned long end;
loff_t size;
int ret;
-
+ pr_info("BUFFER_DEBUG: block_page_mkwrite called for inode %lu, folio index %lu, uptodate=%d\n",
+ inode->i_ino, folio->index, folio_test_uptodate(folio));
folio_lock(folio);
size = i_size_read(inode);
if ((folio->mapping != inode->i_mapping) ||
@@ -2630,7 +2631,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
ret = -EFAULT;
goto out_unlock;
}
-
+ pr_info("BUFFER_DEBUG: Folio checks passed, calling __block_write_begin\n");
end = folio_size(folio);
/* folio is wholly or partially inside EOF */
if (folio_pos(folio) + end > size)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e99306a8f47c..535da8fa9233 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6675,7 +6675,8 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
struct address_space *mapping = inode->i_mapping;
get_block_t *get_block = ext4_get_block;
int retries = 0;
-
+ pr_info("EXT4_DEBUG: ext4_page_mkwrite called for inode %lu, folio index %lu, uptodate=%d\n",
+ inode->i_ino, folio->index, folio_test_uptodate(folio));
if (unlikely(IS_IMMUTABLE(inode)))
return VM_FAULT_SIGBUS;

@@ -6700,19 +6701,27 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
/* Delalloc case is easy... */
if (test_opt(inode->i_sb, DELALLOC) &&
!ext4_nonda_switch(inode->i_sb)) {
+ pr_info("EXT4_DEBUG: Taking delalloc path, calling block_page_mkwrite\n");
do {
err = block_page_mkwrite(vma, vmf,
ext4_da_get_block_prep);
+ pr_info("EXT4_DEBUG: block_page_mkwrite returned err=%d\n", err);
} while (err == -ENOSPC &&
ext4_should_retry_alloc(inode->i_sb, &retries));
goto out_ret;
}

folio_lock(folio);
+ if (!folio_test_uptodate(folio)) {
+ folio_unlock(folio);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }
size = i_size_read(inode);
/* Page got truncated from under us? */
if (folio->mapping != mapping || folio_pos(folio) > size) {
folio_unlock(folio);
+ pr_info("EXT4_DEBUG: Folio truncated, returning VM_FAULT_NOPAGE\n");
ret = VM_FAULT_NOPAGE;
goto out;
}
--
2.43.0

syzbot

unread,
Nov 21, 2025, 3:51:05 AM (14 days ago) Nov 21
to karti...@gmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com
Tested-by: syzbot+b0a067...@syzkaller.appspotmail.com

Tested on:

commit: fd95357f Merge tag 'sched_ext-for-6.18-rc6-fixes-2' of..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=16457a12580000
kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=14e7e8b4580000

Note: testing is done by a robot and is best-effort only.

syzbot

unread,
Nov 21, 2025, 5:44:40 AM (14 days ago) Nov 21
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
fs/ext4/inode.c | 18 +++++++++++++++++-
2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 6a8752f7bbed..805cc0a2ecab 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2621,7 +2621,8 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
unsigned long end;
loff_t size;
int ret;
-
+ pr_info("BUFFER_DEBUG: block_page_mkwrite called for inode %lu, folio index %lu, uptodate=%d\n",
+ inode->i_ino, folio->index, folio_test_uptodate(folio));
folio_lock(folio);
size = i_size_read(inode);
if ((folio->mapping != inode->i_mapping) ||
@@ -2630,7 +2631,7 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
ret = -EFAULT;
goto out_unlock;
}
-
+ pr_info("BUFFER_DEBUG: Folio checks passed, calling __block_write_begin\n");
end = folio_size(folio);
/* folio is wholly or partially inside EOF */
if (folio_pos(folio) + end > size)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e99306a8f47c..776f30993dcd 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6675,7 +6675,8 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
struct address_space *mapping = inode->i_mapping;
get_block_t *get_block = ext4_get_block;
int retries = 0;
-
+ pr_info("EXT4_DEBUG: ext4_page_mkwrite called for inode %lu, folio index %lu, uptodate=%d\n",
+ inode->i_ino, folio->index, folio_test_uptodate(folio));
if (unlikely(IS_IMMUTABLE(inode)))
return VM_FAULT_SIGBUS;

@@ -6688,6 +6689,13 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
if (err)
goto out_ret;

+ folio_lock(folio);
+ if (!folio_test_uptodate(folio)) {
+ folio_unlock(folio);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }
+ folio_unlock(folio);
/*
* On data journalling we skip straight to the transaction handle:
* there's no delalloc; page truncated will be checked later; the
@@ -6700,19 +6708,27 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
/* Delalloc case is easy... */
if (test_opt(inode->i_sb, DELALLOC) &&
!ext4_nonda_switch(inode->i_sb)) {
+ pr_info("EXT4_DEBUG: Taking delalloc path, calling block_page_mkwrite\n");
do {
err = block_page_mkwrite(vma, vmf,
ext4_da_get_block_prep);
+ pr_info("EXT4_DEBUG: block_page_mkwrite returned err=%d\n", err);
} while (err == -ENOSPC &&
ext4_should_retry_alloc(inode->i_sb, &retries));
goto out_ret;
}

folio_lock(folio);
+ /*if (!folio_test_uptodate(folio)) {
+ folio_unlock(folio);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }*/

syzbot

unread,
Nov 21, 2025, 6:32:08 AM (14 days ago) Nov 21
to karti...@gmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com
Tested-by: syzbot+b0a067...@syzkaller.appspotmail.com

Tested on:

commit: fd95357f Merge tag 'sched_ext-for-6.18-rc6-fixes-2' of..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=10720e92580000
kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=10184c2a580000

syzbot

unread,
Nov 21, 2025, 6:52:31 AM (14 days ago) Nov 21
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
index e99306a8f47c..36d988f1758c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6675,7 +6675,8 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
struct address_space *mapping = inode->i_mapping;
get_block_t *get_block = ext4_get_block;
int retries = 0;
-
+ pr_info("EXT4_DEBUG: ext4_page_mkwrite called for inode %lu, folio index %lu, uptodate=%d\n",
+ inode->i_ino, folio->index, folio_test_uptodate(folio));
if (unlikely(IS_IMMUTABLE(inode)))
return VM_FAULT_SIGBUS;

@@ -6688,6 +6689,13 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
if (err)
goto out_ret;

+ folio_lock(folio);

syzbot

unread,
Nov 21, 2025, 7:34:10 AM (14 days ago) Nov 21
to karti...@gmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in __folio_mark_dirty

EXT4-fs error (device loop0): ext4_validate_block_bitmap:441: comm syz-executor349: bg 0: block 112: padding at end of block bitmap is not set
EXT4-fs error (device loop0): ext4_map_blocks:778: inode #15: block 3: comm syz-executor349: lblock 3 mapped to illegal pblock 3 (length 1)
EXT4-fs error (device loop0): ext4_ext_remove_space:2955: inode #15: comm syz-executor349: pblk 0 bad header/extent: invalid extent entries - magic f30a, entries 2, max 4(4), depth 0(0)
EXT4_DEBUG: ext4_page_mkwrite called for inode 15, folio index 0, uptodate=0
------------[ cut here ]------------
WARNING: CPU: 1 PID: 11762 at mm/page-writeback.c:2716 __folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Modules linked in:
CPU: 1 UID: 0 PID: 11762 Comm: syz-executor349 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
RIP: 0010:__folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Code: 3c 38 00 74 08 48 89 df e8 52 a7 26 00 4c 8b 33 4c 89 f6 48 83 e6 08 31 ff e8 d1 ed c4 ff 49 83 e6 08 75 1c e8 66 e8 c4 ff 90 <0f> 0b 90 eb 16 e8 5b e8 c4 ff e9 7e 07 00 00 e8 51 e8 c4 ff eb 05
RSP: 0000:ffffc9000e9079d0 EFLAGS: 00010293
RAX: ffffffff81f9c4ea RBX: ffffea0002ffa540 RCX: ffff88802e261e00
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
R10: dffffc0000000000 R11: fffff940005ff4a9 R12: ffff8880564f0590
R13: ffff8880564f0588 R14: 0000000000000000 R15: dffffc0000000000
FS: 0000555559bd6380(0000) GS:ffff888126ef6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000440 CR3: 0000000040848000 CR4: 00000000003526f0
Call Trace:
<TASK>
block_dirty_folio+0x17a/0x1d0 fs/buffer.c:754
fault_dirty_shared_page+0x103/0x570 mm/memory.c:3519
wp_page_shared mm/memory.c:3906 [inline]
do_wp_page+0x263e/0x4930 mm/memory.c:4109
handle_pte_fault mm/memory.c:6211 [inline]
__handle_mm_fault mm/memory.c:6336 [inline]
handle_mm_fault+0x97c/0x3400 mm/memory.c:6505
do_user_addr_fault+0xa7c/0x1380 arch/x86/mm/fault.c:1336
handle_page_fault arch/x86/mm/fault.c:1476 [inline]
exc_page_fault+0x82/0x100 arch/x86/mm/fault.c:1532
asm_exc_page_fault+0x26/0x30 arch/x86/include/asm/idtentry.h:618
RIP: 0033:0x7f80acffb0c3
Code: 00 00 00 31 c0 e8 ad 43 03 00 bf 02 01 00 00 31 c9 48 ba 40 04 00 00 00 20 00 00 48 b8 2e 2f 66 69 6c 65 30 00 be 9c ff ff ff <48> 89 02 31 c0 e8 83 43 03 00 31 ff e8 1c 76 00 00 66 2e 0f 1f 84
RSP: 002b:00007ffe81efaf50 EFLAGS: 00010246
RAX: 0030656c69662f2e RBX: 0000200000000000 RCX: 0000000000000000
RDX: 0000200000000440 RSI: 00000000ffffff9c RDI: 0000000000000102
RBP: 0000000000000000 R08: 00007ffe81efaf80 R09: 00007ffe81efaf80
R10: 0000000000000e7c R11: 0000000000000246 R12: 00007ffe81efaf6c
R13: 00000000000000e5 R14: 431bde82d7b634db R15: 00007ffe81efafa0
</TASK>


Tested on:

commit: fd95357f Merge tag 'sched_ext-for-6.18-rc6-fixes-2' of..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15839742580000
kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=12647e0a580000

syzbot

unread,
Nov 21, 2025, 7:41:11 AM (14 days ago) Nov 21
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
For archival purposes, forwarding an incoming command email to
linux-...@vger.kernel.org, syzkall...@googlegroups.com.

***

Subject: [PATCH] ext4: check folio uptodate state in ext4_page_mkwrite()
Author: karti...@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


When a write fault occurs on a memory-mapped ext4 file, ext4_page_mkwrite()
is called to prepare the folio for writing. However, if the folio could
not be read successfully due to filesystem corruption or I/O errors, it
will not be marked uptodate.

Attempting to write to a non-uptodate folio is problematic because:
1. We don't have valid data from the backing store to preserve
2. A subsequent writeback could write uninitialized data to disk
3. It triggers a warning in __folio_mark_dirty():
WARN_ON_ONCE(warn && !folio_test_uptodate(folio))

This issue can be reproduced by:
1. Creating a corrupted ext4 filesystem with invalid extent entries
2. Memory-mapping a file on that filesystem
3. Attempting to write to the mapped region

The sequence of events is:
- User accesses mmap region -> page fault
- ext4_filemap_fault() -> ext4_map_blocks() detects corruption
- Returns error, folio allocated but NOT marked uptodate
- User writes to same region -> ext4_page_mkwrite() called
- Without check: folio marked dirty -> WARNING
- With check: return VM_FAULT_SIGBUS immediately

Fix this by checking folio_test_uptodate() early in ext4_page_mkwrite(),
before any code paths (delalloc, journal data, or normal). This ensures
all paths are protected. If the folio is not uptodate, unlock it and
return VM_FAULT_SIGBUS to signal the error to userspace.

fs/ext4/inode.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e99306a8f47c..18a029362c1f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6688,6 +6688,14 @@ vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf)
if (err)
goto out_ret;

+ folio_lock(folio);
+ if (!folio_test_uptodate(folio)) {
+ folio_unlock(folio);
+ ret = VM_FAULT_SIGBUS;
+ goto out;
+ }
+ folio_unlock(folio);
+
/*
* On data journalling we skip straight to the transaction handle:
* there's no delalloc; page truncated will be checked later; the
--
2.43.0

syzbot

unread,
Nov 21, 2025, 8:11:03 AM (14 days ago) Nov 21
to karti...@gmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com
Tested-by: syzbot+b0a067...@syzkaller.appspotmail.com

Tested on:

commit: fd95357f Merge tag 'sched_ext-for-6.18-rc6-fixes-2' of..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15939742580000
kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=1513597c580000

Andrew Morton

unread,
Nov 21, 2025, 1:12:01 PM (14 days ago) Nov 21
to syzbot, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com, wi...@infradead.org
On Thu, 20 Nov 2025 08:41:31 -0800 syzbot <syzbot+b0a067...@syzkaller.appspotmail.com> wrote:

> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: 23cb64fb7625 Merge tag 'soc-fixes-6.18-3' of git://git.ker..
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1287997c580000
> kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
> dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
> compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=172cd658580000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15378484580000
>
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/a14ebce6c664/disk-23cb64fb.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/7703c3032e2f/vmlinux-23cb64fb.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/a16c5b94924d/bzImage-23cb64fb.xz
> mounted in repro: https://storage.googleapis.com/syzbot-assets/4fa9525269b6/mount_0.gz
> fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=11d42a12580000)
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com

Thanks.

: void __folio_mark_dirty(struct folio *folio, struct address_space *mapping,
: int warn)
: {
: unsigned long flags;
:
: /*
: * Shmem writeback relies on swap, and swap writeback is LRU based,
: * not using the dirty mark.
: */
: VM_WARN_ON_ONCE(folio_test_swapcache(folio) || shmem_mapping(mapping));
:
: xa_lock_irqsave(&mapping->i_pages, flags);
: if (folio->mapping) { /* Race with truncate? */
: WARN_ON_ONCE(warn && !folio_test_uptodate(folio));

this

: folio_account_dirtied(folio, mapping);
: __xa_set_mark(&mapping->i_pages, folio->index,
: PAGECACHE_TAG_DIRTY);
: }
: xa_unlock_irqrestore(&mapping->i_pages, flags);
: }

I'm guessing that ext4 permitted a non-uptodate folio to find its way
into the blockdev mapping then the pagefault code tried to modify it
and got upset.

Matthew Wilcox

unread,
Nov 21, 2025, 2:02:25 PM (14 days ago) Nov 21
to Andrew Morton, syzbot, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com
On Fri, Nov 21, 2025 at 10:11:55AM -0800, Andrew Morton wrote:
> On Thu, 20 Nov 2025 08:41:31 -0800 syzbot <syzbot+b0a067...@syzkaller.appspotmail.com> wrote:
> : void __folio_mark_dirty(struct folio *folio, struct address_space *mapping,
> : int warn)
> : {
> : unsigned long flags;
> :
> : /*
> : * Shmem writeback relies on swap, and swap writeback is LRU based,
> : * not using the dirty mark.
> : */
> : VM_WARN_ON_ONCE(folio_test_swapcache(folio) || shmem_mapping(mapping));
> :
> : xa_lock_irqsave(&mapping->i_pages, flags);
> : if (folio->mapping) { /* Race with truncate? */
> : WARN_ON_ONCE(warn && !folio_test_uptodate(folio));
>
> this
>
> : folio_account_dirtied(folio, mapping);
> : __xa_set_mark(&mapping->i_pages, folio->index,
> : PAGECACHE_TAG_DIRTY);
> : }
> : xa_unlock_irqrestore(&mapping->i_pages, flags);
> : }
>
> I'm guessing that ext4 permitted a non-uptodate folio to find its way
> into the blockdev mapping then the pagefault code tried to modify it
> and got upset.

I think you're right, but the reason it's upset is that it found a
!uptodate folio that was mapped into userspace, and that's not supposed
to happen! Presumably it was uptodate at the point it was initially
faulted in, then (perhaps when the error happened?) somebody cleared the
uptodate flag without unmapping the folio.

Hm. I wonder if we should do this to catch the offender:

@@ -831,7 +833,17 @@ static __always_inline void SetPageUptodate(struct page *pa
ge)
folio_mark_uptodate((struct folio *)page);
}

-CLEARPAGEFLAG(Uptodate, uptodate, PF_NO_TAIL)
+static __always_inline void folio_clear_uptodate(struct folio *folio)
+{
+ VM_BUG_ON_FOLIO(folio_mapped(folio), folio);
+ clear_bit(PG_uptodate, folio_flags(folio, 0));
+}
+
+static __always_inline void ClearPageUptodate(struct page *page)
+{
+ VM_BUG_ON_PGFLAGS(PageTail(page), page);
+ folio_clear_uptodate((struct folio *)page);
+}

void __folio_start_writeback(struct folio *folio, bool keep_write);
void set_page_writeback(struct page *page);

... it doesn't actually compile because folio_mapcount() is in mm.h
so the declaration is out of order, but I can invest smoe effort into
making that work if you think it's worth doing.

Andrew Morton

unread,
Nov 21, 2025, 2:14:36 PM (14 days ago) Nov 21
to Matthew Wilcox, syzbot, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com
We have a reproducer, fortunately.

> ... it doesn't actually compile because folio_mapcount() is in mm.h
> so the declaration is out of order, but I can invest smoe effort into
> making that work if you think it's worth doing.

It's a shame to add more debug stuff into oft-called inline functions.

Maybe some hacky thing which uninlines these functions and adds the
debug? I can slip that into -next until we fix the bug then throw the
debug patch away.

Of course, there may be other filesystems which are tripped up by this.
Once we fully understand the failure we can decide whether it's worth
adding the extra debug to mainline?

Theodore Tso

unread,
Dec 2, 2025, 8:26:51 AM (3 days ago) Dec 2
to syzbot, ak...@linux-foundation.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com, wi...@infradead.org
On Thu, Nov 20, 2025 at 08:41:31AM -0800, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: 23cb64fb7625 Merge tag 'soc-fixes-6.18-3' of git://git.ker..
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1287997c580000
> kernel config: https://syzkaller.appspot.com/x/.config?x=38a0c4cddc846161
> dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
> compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=172cd658580000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15378484580000

Not reproducing locally, so let's see if Syzbot can reproduce in its environment....

#syz test https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev

syzbot

unread,
Dec 2, 2025, 8:47:05 AM (3 days ago) Dec 2
to ak...@linux-foundation.org, linux...@vger.kernel.org, linux-...@vger.kernel.org, linux-...@vger.kernel.org, linu...@kvack.org, syzkall...@googlegroups.com, ty...@mit.edu, wi...@infradead.org
Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in __folio_mark_dirty

------------[ cut here ]------------
WARNING: CPU: 1 PID: 6740 at mm/page-writeback.c:2716 __folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Modules linked in:
CPU: 1 UID: 0 PID: 6740 Comm: syz.0.31 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
RIP: 0010:__folio_mark_dirty+0x1fb/0xe20 mm/page-writeback.c:2716
Code: 3c 38 00 74 08 48 89 df e8 d2 a1 26 00 4c 8b 33 4c 89 f6 48 83 e6 08 31 ff e8 71 ef c4 ff 49 83 e6 08 75 1c e8 06 ea c4 ff 90 <0f> 0b 90 eb 16 e8 fb e9 c4 ff e9 7e 07 00 00 e8 f1 e9 c4 ff eb 05
RSP: 0018:ffffc90003a979d0 EFLAGS: 00010293
RAX: ffffffff81f9d61a RBX: ffffea0001056b40 RCX: ffff888020775a00
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
R10: dffffc0000000000 R11: fffff9400020ad69 R12: ffff88805b014d00
R13: ffff88805b014cf8 R14: 0000000000000000 R15: dffffc0000000000
FS: 0000555575052500(0000) GS:ffff888126ef6000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000440 CR3: 0000000036d66000 CR4: 00000000003526f0
Call Trace:
<TASK>
block_dirty_folio+0x17a/0x1d0 fs/buffer.c:754
fault_dirty_shared_page+0x103/0x570 mm/memory.c:3518
wp_page_shared mm/memory.c:3905 [inline]
do_wp_page+0x263e/0x4930 mm/memory.c:4108
handle_pte_fault mm/memory.c:6193 [inline]
__handle_mm_fault mm/memory.c:6318 [inline]
handle_mm_fault+0x97c/0x3400 mm/memory.c:6487
do_user_addr_fault+0xa7c/0x1380 arch/x86/mm/fault.c:1336
handle_page_fault arch/x86/mm/fault.c:1476 [inline]
exc_page_fault+0x82/0x100 arch/x86/mm/fault.c:1532
asm_exc_page_fault+0x26/0x30 arch/x86/include/asm/idtentry.h:618
RIP: 0033:0x7f1eba837398
Code: fc 89 37 c3 c5 fa 6f 06 c5 fa 6f 4c 16 f0 c5 fa 7f 07 c5 fa 7f 4c 17 f0 c3 66 0f 1f 84 00 00 00 00 00 48 8b 4c 16 f8 48 8b 36 <48> 89 37 48 89 4c 17 f8 c3 c5 fe 6f 54 16 e0 c5 fe 6f 5c 16 c0 c5
RSP: 002b:00007ffd39d5fc68 EFLAGS: 00010246
RAX: 0000200000000440 RBX: 0000000000000004 RCX: 0030656c69662f2e
RDX: 0000000000000008 RSI: 0030656c69662f2e RDI: 0000200000000440
RBP: 00007f1ebaac7da0 R08: 0000001b2cc20000 R09: 0000000000000001
R10: 0000000000000001 R11: 0000000000000009 R12: 00007f1ebaac5fac
R13: 00007f1ebaac5fa0 R14: fffffffffffffffe R15: 00007ffd39d5fd80
</TASK>


Tested on:

commit: 6fb67ac8 ext4: drop the TODO comment in ext4_es_insert..
git tree: https://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git dev
console output: https://syzkaller.appspot.com/x/log.txt?x=16156192580000
kernel config: https://syzkaller.appspot.com/x/.config?x=41ad820f608cb833
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8

Note: no patches were applied.

syzbot

unread,
Dec 4, 2025, 11:54:29 PM (3 hours ago) Dec 4
to linux-...@vger.kernel.org, syzkall...@googlegroups.com
For archival purposes, forwarding an incoming command email to
linux-...@vger.kernel.org, syzkall...@googlegroups.com.

***

Subject: [PATCH v3] ext4: unmap invalidated folios from page tables in mpage_release_unused_pages()
When delayed block allocation fails (e.g., due to filesystem corruption
detected in ext4_map_blocks()), the writeback error handler calls
mpage_release_unused_pages(invalidate=true) which invalidates affected
folios by clearing their uptodate flag via folio_clear_uptodate().

However, these folios may still be mapped in process page tables. If a
subsequent operation (such as ftruncate calling ext4_block_truncate_page)
triggers a write fault, the existing page table entry allows access to
the now-invalidated folio. This leads to ext4_page_mkwrite() being called
with a non-uptodate folio, which then gets marked dirty, triggering:

WARNING: CPU: 0 PID: 5 at mm/page-writeback.c:2960
__folio_mark_dirty+0x578/0x880

Call Trace:
fault_dirty_shared_page+0x16e/0x2d0
do_wp_page+0x38b/0xd20
handle_pte_fault+0x1da/0x450

The sequence leading to this warning is:

1. Process writes to mmap'd file, folio becomes uptodate and dirty
2. Writeback begins, but delayed allocation fails due to corruption
3. mpage_release_unused_pages(invalidate=true) is called:
- block_invalidate_folio() clears dirty flag
- folio_clear_uptodate() clears uptodate flag
- But folio remains mapped in page tables
4. Later, ftruncate triggers ext4_block_truncate_page()
5. This causes a write fault on the still-mapped folio
6. ext4_page_mkwrite() is called with folio that is !uptodate
7. block_page_mkwrite() marks buffers dirty
8. fault_dirty_shared_page() tries to mark folio dirty
9. block_dirty_folio() calls __folio_mark_dirty(warn=1)
10. WARNING triggers: WARN_ON_ONCE(warn && !uptodate && !dirty)

Fix this by unmapping folios from page tables before invalidating them
using unmap_mapping_pages(). This ensures that subsequent accesses
trigger new page faults rather than reusing invalidated folios through
stale page table entries.

Note that this results in data loss for any writes to the mmap'd region
that couldn't be written back, but this is expected behavior when
writeback fails due to filesystem corruption. The existing error message
already states "This should not happen!! Data will be lost".
fs/ext4/inode.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e99306a8f47c..16f73c0c33c4 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1749,8 +1749,17 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd,
BUG_ON(!folio_test_locked(folio));
BUG_ON(folio_test_writeback(folio));
if (invalidate) {
- if (folio_mapped(folio))
+ if (folio_mapped(folio)) {
folio_clear_dirty_for_io(folio);
+ /*
+ * Unmap folio from page tables to prevent subsequent
+ * accesses through stale PTEs. This ensures future
+ * accesses trigger new page faults rather than reusing
+ * the invalidated folio.
+ */
+ unmap_mapping_pages(folio->mapping, folio->index,
+ folio_nr_pages(folio), false);
+ }
block_invalidate_folio(folio, 0,
folio_size(folio));
folio_clear_uptodate(folio);
--
2.43.0

syzbot

unread,
12:33 AM (3 hours ago) 12:33 AM
to karti...@gmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+b0a067...@syzkaller.appspotmail.com
Tested-by: syzbot+b0a067...@syzkaller.appspotmail.com

Tested on:

commit: 2061f18a Merge tag 'caps-pr-20251204' of git://git.ker..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1473b01a580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8a99cdde3da055cf
dashboard link: https://syzkaller.appspot.com/bug?extid=b0a0670332b6b3230a0a
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=10bdb01a580000
Reply all
Reply to author
Forward
0 new messages