[syzbot] [nilfs?] general protection fault in touch_buffer

8 views
Skip to first unread message

syzbot

unread,
Oct 30, 2024, 1:45:27 PM10/30/24
to konishi...@gmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot found the following issue on:

HEAD commit: c1e939a21eb1 Merge tag 'cgroup-for-6.12-rc5-fixes' of git:..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15bd4e87980000
kernel config: https://syzkaller.appspot.com/x/.config?x=4aec7739e14231a7
dashboard link: https://syzkaller.appspot.com/bug?extid=9982fb8d18eba905abe2
compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=17e24630580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1427255f980000

Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/7feb34a89c2a/non_bootable_disk-c1e939a2.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/79a07b922222/vmlinux-c1e939a2.xz
kernel image: https://storage.googleapis.com/syzbot-assets/0a5d98e2bb0d/bzImage-c1e939a2.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/e4ead0d018d8/mount_0.gz

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

loop0: detected capacity change from 0 to 2048
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
CPU: 0 UID: 0 PID: 5503 Comm: syz-executor197 Not tainted 6.12.0-rc5-syzkaller-00044-gc1e939a21eb1 #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:perf_trace_block_buffer+0x293/0x490 include/trace/events/block.h:24
Code: 24 18 48 8d 58 30 48 89 d8 48 c1 e8 03 42 80 3c 28 00 74 08 48 89 df e8 2b 82 62 fd 4c 8b 3b 49 83 c7 34 4c 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 6c 01 00 00 45 8b 3f 49 8d 5c 24 08 48
RSP: 0018:ffffc9000d4ef420 EFLAGS: 00010207
RAX: 0000000000000006 RBX: ffff888049091030 RCX: ffff88801f02c880
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88801fc37928
RBP: ffffc9000d4ef518 R08: ffffffff819e732b R09: 1ffffffff203a095
R10: dffffc0000000000 R11: fffffbfff203a096 R12: ffffe8ffffc33cd0
R13: dffffc0000000000 R14: ffff88801fc378a0 R15: 0000000000000034
FS: 00007f230dad76c0(0000) GS:ffff88801fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffebac93808 CR3: 0000000043d34000 CR4: 0000000000352ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
trace_block_touch_buffer include/trace/events/block.h:54 [inline]
touch_buffer+0x1d5/0x240 fs/buffer.c:64
__nilfs_get_folio_block fs/nilfs2/page.c:42 [inline]
nilfs_grab_buffer+0x321/0x440 fs/nilfs2/page.c:61
nilfs_mdt_submit_block+0xdc/0x890 fs/nilfs2/mdt.c:121
nilfs_mdt_read_block+0xeb/0x430 fs/nilfs2/mdt.c:176
nilfs_mdt_get_block+0x127/0xb70 fs/nilfs2/mdt.c:251
nilfs_palloc_get_block+0x181/0x2a0 fs/nilfs2/alloc.c:217
nilfs_palloc_get_entry_block+0x8e/0xb0 fs/nilfs2/alloc.c:319
nilfs_ifile_get_inode_block+0xed/0x180 fs/nilfs2/ifile.c:141
__nilfs_read_inode fs/nilfs2/inode.c:476 [inline]
nilfs_iget+0x240/0x810 fs/nilfs2/inode.c:581
nilfs_get_root_dentry+0x28/0x230 fs/nilfs2/super.c:909
nilfs_fill_super+0x50b/0x720 fs/nilfs2/super.c:1090
nilfs_get_tree+0x4f9/0x920 fs/nilfs2/super.c:1220
vfs_get_tree+0x90/0x2b0 fs/super.c:1800
do_new_mount+0x2be/0xb40 fs/namespace.c:3507
do_mount fs/namespace.c:3847 [inline]
__do_sys_mount fs/namespace.c:4057 [inline]
__se_sys_mount+0x2d6/0x3c0 fs/namespace.c:4034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f230db220da
Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 5e 04 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f230dad7088 EFLAGS: 00000286 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007f230dad70a0 RCX: 00007f230db220da
RDX: 0000000020000000 RSI: 0000000020000040 RDI: 00007f230dad70a0
RBP: 0000000000000004 R08: 00007f230dad70e0 R09: 0000000000000aa1
R10: 0000000003200c00 R11: 0000000000000286 R12: 00007f230dad70e0
R13: 0000000003200c00 R14: 0000000000000003 R15: 0000000000100000
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:perf_trace_block_buffer+0x293/0x490 include/trace/events/block.h:24
Code: 24 18 48 8d 58 30 48 89 d8 48 c1 e8 03 42 80 3c 28 00 74 08 48 89 df e8 2b 82 62 fd 4c 8b 3b 49 83 c7 34 4c 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 6c 01 00 00 45 8b 3f 49 8d 5c 24 08 48
RSP: 0018:ffffc9000d4ef420 EFLAGS: 00010207
RAX: 0000000000000006 RBX: ffff888049091030 RCX: ffff88801f02c880
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88801fc37928
RBP: ffffc9000d4ef518 R08: ffffffff819e732b R09: 1ffffffff203a095
R10: dffffc0000000000 R11: fffffbfff203a096 R12: ffffe8ffffc33cd0
R13: dffffc0000000000 R14: ffff88801fc378a0 R15: 0000000000000034
FS: 00007f230dad76c0(0000) GS:ffff88801fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffebac93808 CR3: 0000000043d34000 CR4: 0000000000352ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
----------------
Code disassembly (best guess):
0: 24 18 and $0x18,%al
2: 48 8d 58 30 lea 0x30(%rax),%rbx
6: 48 89 d8 mov %rbx,%rax
9: 48 c1 e8 03 shr $0x3,%rax
d: 42 80 3c 28 00 cmpb $0x0,(%rax,%r13,1)
12: 74 08 je 0x1c
14: 48 89 df mov %rbx,%rdi
17: e8 2b 82 62 fd call 0xfd628247
1c: 4c 8b 3b mov (%rbx),%r15
1f: 49 83 c7 34 add $0x34,%r15
23: 4c 89 f8 mov %r15,%rax
26: 48 c1 e8 03 shr $0x3,%rax
* 2a: 42 0f b6 04 28 movzbl (%rax,%r13,1),%eax <-- trapping instruction
2f: 84 c0 test %al,%al
31: 0f 85 6c 01 00 00 jne 0x1a3
37: 45 8b 3f mov (%r15),%r15d
3a: 49 8d 5c 24 08 lea 0x8(%r12),%rbx
3f: 48 rex.W


---
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

Edward Adam Davis

unread,
Oct 31, 2024, 8:26:31 AM10/31/24
to syzbot+9982fb...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
debug

#syz test

diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 9c0b7cddeaae..63831711077f 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -32,12 +32,21 @@ static struct buffer_head *__nilfs_get_folio_block(struct folio *folio,
{
unsigned long first_block;
struct buffer_head *bh = folio_buffers(folio);
+ u32 fs = folio_size(folio);
+ int fpr = folio_nr_pages(folio);
+ printk("bh: %p, folio size: %u, folio nr pages: %d, %s\n", bh, fs, fpr, __func__);

if (!bh)
bh = create_empty_buffers(folio, 1 << blkbits, b_state);

first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
+ printk("bh: %p, blk: %lu, first blk: %lu, blkbits: %d, idx: %lu, %s\n", bh, block, first_block, blkbits, index, __func__);
+ BUG_ON(block < first_block);
+ if (fs >> blkbits < (block - first_block))
+ printk("folio size is too small %s\n", __func__);
+
bh = get_nth_bh(bh, block - first_block);
+ printk("after get nth bh: %p, %s\n", bh, __func__);

touch_buffer(bh);
wait_on_buffer(bh);
Upstream-Status: Pending

syzbot

unread,
Oct 31, 2024, 8:47:08 AM10/31/24
to ead...@qq.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
general protection fault in touch_buffer

bh: ffff88801fcf9910, folio size: 4096, folio nr pages: 1, __nilfs_get_folio_block
bh: ffff88801fcf9910, blk: 3, first blk: 0, blkbits: 10, idx: 0, __nilfs_get_folio_block
after get nth bh: ffff88801fd4c9f8, __nilfs_get_folio_block
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
CPU: 0 UID: 0 PID: 6143 Comm: syz.0.57 Not tainted 6.12.0-rc5-syzkaller-g0fc810ae3ae1-dirty #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:perf_trace_block_buffer+0x293/0x490 include/trace/events/block.h:24
Code: 24 18 48 8d 58 30 48 89 d8 48 c1 e8 03 42 80 3c 28 00 74 08 48 89 df e8 8b 7d 62 fd 4c 8b 3b 49 83 c7 34 4c 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 6c 01 00 00 45 8b 3f 49 8d 5c 24 08 48
RSP: 0018:ffffc9000d2d7400 EFLAGS: 00010207
RAX: 0000000000000006 RBX: ffff88801fd4ca28 RCX: ffff8880363e2440
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88801fc37928
RBP: ffffc9000d2d74f0 R08: ffffffff819e732b R09: 1ffffffff203a0bd
R10: dffffc0000000000 R11: fffffbfff203a0be R12: ffffe8ffffc88e78
R13: dffffc0000000000 R14: ffff88801fc378a0 R15: 0000000000000034
FS: 00007f849423c6c0(0000) GS:ffff88801fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b2f45ffff CR3: 000000005600e000 CR4: 0000000000352ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
trace_block_touch_buffer include/trace/events/block.h:54 [inline]
touch_buffer+0x1d5/0x240 fs/buffer.c:64
__nilfs_get_folio_block fs/nilfs2/page.c:51 [inline]
nilfs_grab_buffer+0x56b/0x8d0 fs/nilfs2/page.c:70
nilfs_mdt_submit_block+0xdc/0x890 fs/nilfs2/mdt.c:121
nilfs_mdt_read_block+0x150/0x430 fs/nilfs2/mdt.c:186
nilfs_mdt_get_block+0x127/0xb70 fs/nilfs2/mdt.c:251
nilfs_palloc_get_block+0x181/0x2a0 fs/nilfs2/alloc.c:217
nilfs_palloc_get_entry_block+0x8e/0xb0 fs/nilfs2/alloc.c:319
nilfs_ifile_get_inode_block+0xed/0x180 fs/nilfs2/ifile.c:141
__nilfs_read_inode fs/nilfs2/inode.c:476 [inline]
nilfs_iget+0x240/0x810 fs/nilfs2/inode.c:581
nilfs_get_root_dentry+0x28/0x230 fs/nilfs2/super.c:909
nilfs_fill_super+0x50b/0x720 fs/nilfs2/super.c:1090
nilfs_get_tree+0x4f9/0x920 fs/nilfs2/super.c:1220
vfs_get_tree+0x90/0x2b0 fs/super.c:1800
do_new_mount+0x2be/0xb40 fs/namespace.c:3507
do_mount fs/namespace.c:3847 [inline]
__do_sys_mount fs/namespace.c:4057 [inline]
__se_sys_mount+0x2d6/0x3c0 fs/namespace.c:4034
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f849337feba
Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 de 1a 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f849423be68 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007f849423bef0 RCX: 00007f849337feba
RDX: 0000000020000000 RSI: 0000000020000040 RDI: 00007f849423beb0
RBP: 0000000020000000 R08: 00007f849423bef0 R09: 0000000003200c00
R10: 0000000003200c00 R11: 0000000000000246 R12: 0000000020000040
R13: 00007f849423beb0 R14: 0000000000000aa7 R15: 0000000020001bc0
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:perf_trace_block_buffer+0x293/0x490 include/trace/events/block.h:24
Code: 24 18 48 8d 58 30 48 89 d8 48 c1 e8 03 42 80 3c 28 00 74 08 48 89 df e8 8b 7d 62 fd 4c 8b 3b 49 83 c7 34 4c 89 f8 48 c1 e8 03 <42> 0f b6 04 28 84 c0 0f 85 6c 01 00 00 45 8b 3f 49 8d 5c 24 08 48
RSP: 0018:ffffc9000d2d7400 EFLAGS: 00010207
RAX: 0000000000000006 RBX: ffff88801fd4ca28 RCX: ffff8880363e2440
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88801fc37928
RBP: ffffc9000d2d74f0 R08: ffffffff819e732b R09: 1ffffffff203a0bd
R10: dffffc0000000000 R11: fffffbfff203a0be R12: ffffe8ffffc88e78
R13: dffffc0000000000 R14: ffff88801fc378a0 R15: 0000000000000034
FS: 00007f849423c6c0(0000) GS:ffff88801fc00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001b2f45ffff CR3: 000000005600e000 CR4: 0000000000352ef0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
----------------
Code disassembly (best guess):
0: 24 18 and $0x18,%al
2: 48 8d 58 30 lea 0x30(%rax),%rbx
6: 48 89 d8 mov %rbx,%rax
9: 48 c1 e8 03 shr $0x3,%rax
d: 42 80 3c 28 00 cmpb $0x0,(%rax,%r13,1)
12: 74 08 je 0x1c
14: 48 89 df mov %rbx,%rdi
17: e8 8b 7d 62 fd call 0xfd627da7
1c: 4c 8b 3b mov (%rbx),%r15
1f: 49 83 c7 34 add $0x34,%r15
23: 4c 89 f8 mov %r15,%rax
26: 48 c1 e8 03 shr $0x3,%rax
* 2a: 42 0f b6 04 28 movzbl (%rax,%r13,1),%eax <-- trapping instruction
2f: 84 c0 test %al,%al
31: 0f 85 6c 01 00 00 jne 0x1a3
37: 45 8b 3f mov (%r15),%r15d
3a: 49 8d 5c 24 08 lea 0x8(%r12),%rbx
3f: 48 rex.W


Tested on:

commit: 0fc810ae x86/uaccess: Avoid barrier_nospec() in 64-bit..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=106b655f980000
kernel config: https://syzkaller.appspot.com/x/.config?x=4aec7739e14231a7
dashboard link: https://syzkaller.appspot.com/bug?extid=9982fb8d18eba905abe2
compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
patch: https://syzkaller.appspot.com/x/patch.diff?x=14e92630580000

Ryusuke Konishi

unread,
Nov 1, 2024, 8:10:01 PM11/1/24
to syzbot+9982fb...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com
The cause of this problem seems to be that bh->b_bdev is not set when
touch_buffer() is called (it is set later by the calling functions).

This causes a general protection fault when the trace point
trace_block_touch_buffer() in touch_buffer() references
bh->b_bdev->bd_dev.

touch_buffer() mark the folio owned by the buffer as accessed by
calling folio_mark_accessed(), but nilfs_grab_buffer(), the only
caller of __nilfs_get_folio_block(), acquires the folio through
filemap_grab_folio(), which sets the folio as accessed by specifying
the FGP_ACCESSED flag, so there is not need to call touch_buffer() in
the first place.

Once I have confirmed that there is not problem, including the past
history, I will turn this into a formal bug fix patch.

Ryusuke Konishi


#syz test

diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 10def4b55995..296dbf9cca22 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -39,7 +39,6 @@ static struct buffer_head *__nilfs_get_folio_block(struct folio *folio,
first_block = (unsigned long)index << (PAGE_SHIFT - blkbits);
bh = get_nth_bh(bh, block - first_block);

- touch_buffer(bh);
wait_on_buffer(bh);
return bh;
}
--
2.43.0

syzbot

unread,
Nov 1, 2024, 8:30:07 PM11/1/24
to konishi...@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+9982fb...@syzkaller.appspotmail.com
Tested-by: syzbot+9982fb...@syzkaller.appspotmail.com

Tested on:

commit: c4264568 Merge tag 'acpi-6.12-rc6' of git://git.kernel..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1454f2a7980000
kernel config: https://syzkaller.appspot.com/x/.config?x=4aec7739e14231a7
dashboard link: https://syzkaller.appspot.com/bug?extid=9982fb8d18eba905abe2
compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
patch: https://syzkaller.appspot.com/x/patch.diff?x=1726555f980000

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

Ryusuke Konishi

unread,
Nov 6, 2024, 11:08:20 AM11/6/24
to Andrew Morton, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzbot, syzkall...@googlegroups.com, bugr...@valiantsec.com
Hi Andrew, please add this series to the queue for the next cycle.

This series fixes null pointer dereference bugs that occur when using
nilfs2 and two block-related tracepoints.

Thanks,
Ryusuke Konishi

Ryusuke Konishi (2):
nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint
nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint

fs/nilfs2/btnode.c | 2 --
fs/nilfs2/gcinode.c | 4 +---
fs/nilfs2/mdt.c | 1 -
fs/nilfs2/page.c | 2 +-
4 files changed, 2 insertions(+), 7 deletions(-)

--
2.43.0

Ryusuke Konishi

unread,
Nov 6, 2024, 11:08:22 AM11/6/24
to Andrew Morton, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzbot, syzkall...@googlegroups.com, bugr...@valiantsec.com
It has been reported that when using "block:block_touch_buffer"
tracepoint, touch_buffer() called from __nilfs_get_folio_block() causes
a NULL pointer dereference, or a general protection fault when KASAN is
enabled.

This happens because since the tracepoint was added in touch_buffer(),
it references the dev_t member bh->b_bdev->bd_dev regardless of whether
the buffer head has a pointer to a block_device structure. In the
current implementation, the block_device structure is set after the
function returns to the caller.

Here, touch_buffer() is used to mark the folio/page that owns the buffer
head as accessed, but the common search helper for folio/page used by
the caller function was optimized to mark the folio/page as accessed
when it was reimplemented a long time ago, eliminating the need to call
touch_buffer() here in the first place.

So this solves the issue by eliminating the touch_buffer() call itself.

Signed-off-by: Ryusuke Konishi <konishi...@gmail.com>
Reported-by: Ubisectech Sirius <bugr...@valiantsec.com>
Closes: https://lkml.kernel.org/r/86bd3013-887e-4e38-960f...@valiantsec.com
Reported-by: syzbot+9982fb...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9982fb8d18eba905abe2
Fixes: 5305cb830834 ("block: add block_{touch|dirty}_buffer tracepoint")
Tested-by: syzbot+9982fb...@syzkaller.appspotmail.com
Cc: sta...@vger.kernel.org
---
fs/nilfs2/page.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index e48079ebe939..bdc4b152f6e9 100644

Ryusuke Konishi

unread,
Nov 6, 2024, 11:08:23 AM11/6/24
to Andrew Morton, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzbot, syzkall...@googlegroups.com, bugr...@valiantsec.com
When using the "block:block_dirty_buffer" tracepoint,
mark_buffer_dirty() may cause a NULL pointer dereference, or a general
protection fault when KASAN is enabled.

This happens because, since the tracepoint was added in
mark_buffer_dirty(), it references the dev_t member bh->b_bdev->bd_dev
regardless of whether the buffer head has a pointer to a block_device
structure.

In the current implementation, nilfs_grab_buffer(), which grabs a buffer
to read (or create) a block of metadata, including b-tree node blocks,
does not set the block device, but instead does so only if the buffer is
not in the "uptodate" state for each of its caller block reading
functions. However, if the uptodate flag is set on a folio/page, and
the buffer heads are detached from it by try_to_free_buffers(), and new
buffer heads are then attached by create_empty_buffers(), the uptodate
flag may be restored to each buffer without the block device being set
to bh->b_bdev, and mark_buffer_dirty() may be called later in that
state, resulting in the bug mentioned above.

Fix this issue by making nilfs_grab_buffer() always set the block device
of the super block structure to the buffer head, regardless of the state
of the buffer's uptodate flag.

Signed-off-by: Ryusuke Konishi <konishi...@gmail.com>
Fixes: 5305cb830834 ("block: add block_{touch|dirty}_buffer tracepoint")
Cc: sta...@vger.kernel.org
---
fs/nilfs2/btnode.c | 2 --
fs/nilfs2/gcinode.c | 4 +---
fs/nilfs2/mdt.c | 1 -
fs/nilfs2/page.c | 1 +
4 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index 57b4af5ad646..501ad7be5174 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -68,7 +68,6 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr)
goto failed;
}
memset(bh->b_data, 0, i_blocksize(inode));
- bh->b_bdev = inode->i_sb->s_bdev;
bh->b_blocknr = blocknr;
set_buffer_mapped(bh);
set_buffer_uptodate(bh);
@@ -133,7 +132,6 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr,
goto found;
}
set_buffer_mapped(bh);
- bh->b_bdev = inode->i_sb->s_bdev;
bh->b_blocknr = pblocknr; /* set block address for read */
bh->b_end_io = end_buffer_read_sync;
get_bh(bh);
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index 1c9ae36a03ab..ace22253fed0 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -83,10 +83,8 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff,
goto out;
}

- if (!buffer_mapped(bh)) {
- bh->b_bdev = inode->i_sb->s_bdev;
+ if (!buffer_mapped(bh))
set_buffer_mapped(bh);
- }
bh->b_blocknr = pbn;
bh->b_end_io = end_buffer_read_sync;
get_bh(bh);
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 432181cfb0b5..965b5ad1c0df 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -92,7 +92,6 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block,
if (buffer_uptodate(bh))
goto failed_bh;

- bh->b_bdev = sb->s_bdev;
err = nilfs_mdt_insert_new_block(inode, block, bh, init_block);
if (likely(!err)) {
get_bh(bh);
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index bdc4b152f6e9..bd86447d2edf 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -63,6 +63,7 @@ struct buffer_head *nilfs_grab_buffer(struct inode *inode,
folio_put(folio);
return NULL;
}
+ bh->b_bdev = inode->i_sb->s_bdev;
return bh;
}

--
2.43.0

Reply all
Reply to author
Forward
0 new messages