Bug 203227

Summary: kernel BUG at fs/f2fs/recovery.c:549! and hangs on sync
Product: File System Reporter: Jungyeon (jungyeon)
Component: f2fsAssignee: Default virtual assignee for f2fs (filesystem_f2fs)
Status: RESOLVED CODE_FIX    
Severity: normal CC: chao
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 5.0.0 Subsystem:
Regression: No Bisected commit-id:
Attachments: The (compressed) crafted image which causes crash

Description Jungyeon 2019-04-09 22:45:25 UTC
Created attachment 282229 [details]
The (compressed) crafted image which causes crash

- Overview
When mounting the attached crafted image, following errors are reported.
Additionally, it hangs on sync after trying to mount it.

The image is intentionally fuzzed from a normal f2fs image for testing.
Compile options for F2FS are as follows.
CONFIG_F2FS_FS=y
CONFIG_F2FS_STAT_FS=y
CONFIG_F2FS_FS_XATTR=y
CONFIG_F2FS_FS_POSIX_ACL=y
# CONFIG_F2FS_FS_SECURITY is not set
CONFIG_F2FS_CHECK_FS=y
# CONFIG_F2FS_FS_ENCRYPTION is not set
# CONFIG_F2FS_FAULT_INJECTION is not set

- Reproduces
mkdir test
mount -t f2fs tmp.img test
sync

- Messages
[   38.315948] F2FS-fs (sdb): Can't find valid F2FS filesystem in 2th superblock
[   38.320145] kernel BUG at fs/f2fs/recovery.c:549!
[   38.320971] invalid opcode: 0000 [#1] SMP PTI
[   38.321556] CPU: 0 PID: 1878 Comm: mount Not tainted 5.0.0 #5
[   38.322349] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[   38.323594] RIP: 0010:recover_data+0x167a/0x1780
[   38.324211] Code: 00 00 83 e0 f8 89 8a e8 0f 00 00 89 c1 8b 82 f0 0f 00 00 83 e0 07 09 c8 89 82 f0 0f 00 00 e8 6d ca e1 ff e9 71 fd ff ff 0f 0b <0f> 0b f6 40 03 20 0f 84 d8 fc ff ff 0f b7 88 68 01 00 00 66 c1 e9
[   38.326697] RSP: 0018:ffffbd3fc0cfbb18 EFLAGS: 00010287
[   38.327386] RAX: ffffa211f13f6000 RBX: 00000000129fa2df RCX: 000000001ffca000
[   38.328332] RDX: ffffa211ec3dc000 RSI: ffffa20fc0000000 RDI: 000000000004b01e
[   38.329258] RBP: ffffa211eebe8cc0 R08: ffffa211eebf3298 R09: 0000000000000009
[   38.330220] R10: ffffe6fa88b0f700 R11: ffffe6fa80000000 R12: 00000000000003fa
[   38.331176] R13: ffffa211eea9f0a0 R14: 0000000000000000 R15: ffffe6fa88c4fd80
[   38.332104] FS:  00007f4acee4e840(0000) GS:ffffa211f7a00000(0000) knlGS:0000000000000000
[   38.333180] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   38.333996] CR2: 00007ffed1517d3c CR3: 000000022c480004 CR4: 00000000001606f0
[   38.334940] Call Trace:
[   38.335291]  ? mark_page_accessed+0x9c/0x110
[   38.335862]  ? pagecache_get_page+0x177/0x210
[   38.336456]  f2fs_recover_fsync_data+0x613/0x710
[   38.337065]  ? proc_create_single_data+0x37/0x50
[   38.337719]  f2fs_fill_super+0x1043/0x1aa0
[   38.338297]  ? f2fs_commit_super+0x180/0x180
[   38.338862]  mount_bdev+0x16d/0x1a0
[   38.339326]  mount_fs+0x4a/0x170
[   38.339759]  vfs_kern_mount+0x5d/0x100
[   38.340259]  do_mount+0x200/0xcf0
[   38.340711]  ? memdup_user+0x39/0x60
[   38.341208]  ksys_mount+0x79/0xc0
[   38.341670]  __x64_sys_mount+0x1c/0x20
[   38.342184]  do_syscall_64+0x43/0xf0
[   38.342662]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   38.343346] RIP: 0033:0x7f4ace72db9a
[   38.343822] Code: 48 8b 0d 01 c3 2b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d ce c2 2b 00 f7 d8 64 89 01 48
[   38.346264] RSP: 002b:00007ffed1519568 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
[   38.347260] RAX: ffffffffffffffda RBX: 0000000001535050 RCX: 00007f4ace72db9a
[   38.348191] RDX: 0000000001535230 RSI: 0000000001535f20 RDI: 0000000001535250
[   38.349120] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000013
[   38.350066] R10: 00000000c0ed0000 R11: 0000000000000202 R12: 0000000001535250
[   38.350990] R13: 0000000001535230 R14: 0000000000000000 R15: 0000000000000003
[   38.351938] Modules linked in:
[   38.352374] ---[ end trace 763c06721205a251 ]---
[   38.352989] RIP: 0010:recover_data+0x167a/0x1780
[   38.353615] Code: 00 00 83 e0 f8 89 8a e8 0f 00 00 89 c1 8b 82 f0 0f 00 00 83 e0 07 09 c8 89 82 f0 0f 00 00 e8 6d ca e1 ff e9 71 fd ff ff 0f 0b <0f> 0b f6 40 03 20 0f 84 d8 fc ff ff 0f b7 88 68 01 00 00 66 c1 e9
[   38.356070] RSP: 0018:ffffbd3fc0cfbb18 EFLAGS: 00010287
[   38.356763] RAX: ffffa211f13f6000 RBX: 00000000129fa2df RCX: 000000001ffca000
[   38.357746] RDX: ffffa211ec3dc000 RSI: ffffa20fc0000000 RDI: 000000000004b01e
[   38.358706] RBP: ffffa211eebe8cc0 R08: ffffa211eebf3298 R09: 0000000000000009
[   38.359641] R10: ffffe6fa88b0f700 R11: ffffe6fa80000000 R12: 00000000000003fa
[   38.360594] R13: ffffa211eea9f0a0 R14: 0000000000000000 R15: ffffe6fa88c4fd80
[   38.361570] FS:  00007f4acee4e840(0000) GS:ffffa211f7a00000(0000) knlGS:0000000000000000
[   38.362633] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   38.363393] CR2: 00007ffed1517d3c CR3: 000000022c480004 CR4: 00000000001606f0
[   38.365045] mount (1878) used greatest stack depth: 13320 bytes left

- Error location
505 static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
506                     struct page *page)
507 {
508     struct dnode_of_data dn;
509     struct node_info ni;
510     unsigned int start, end;
511     int err = 0, recovered = 0;
512 
513     /* step 1: recover xattr */
514     if (IS_INODE(page)) {
515         f2fs_recover_inline_xattr(inode, page);
516     } else if (f2fs_has_xattr_block(ofs_of_node(page))) {
517         err = f2fs_recover_xattr_data(inode, page);
518         if (!err)
519             recovered++;
520         goto out;
521     }
522 
523     /* step 2: recover inline data */
524     if (f2fs_recover_inline_data(inode, page))
525         goto out;
526 
527     /* step 3: recover data indices */
528     start = f2fs_start_bidx_of_node(ofs_of_node(page), inode);
529     end = start + ADDRS_PER_PAGE(page, inode);
530 
531     set_new_dnode(&dn, inode, NULL, NULL, 0);
532 retry_dn:
533     err = f2fs_get_dnode_of_data(&dn, start, ALLOC_NODE);
534     if (err) {
535         if (err == -ENOMEM) {
536             congestion_wait(BLK_RW_ASYNC, HZ/50);
537             goto retry_dn;
538         }
539         goto out;
540     }
541 
542     f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
543 
544     err = f2fs_get_node_info(sbi, dn.nid, &ni);
545     if (err)
546         goto err;
547 
548     f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
*549     f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page));
550
Comment 1 Chao Yu 2019-04-15 14:53:06 UTC
Fixed with

f2fs: fix to avoid panic in do_recover_data()