• Qu Wenruo's avatar
    btrfs: ctree: check key order before merging tree blocks · d16c702f
    Qu Wenruo authored
    [BUG]
    With a crafted image, btrfs can panic at btrfs_del_csums():
    
      kernel BUG at fs/btrfs/ctree.c:3188!
      invalid opcode: 0000 [#1] SMP PTI
      CPU: 0 PID: 1156 Comm: btrfs-transacti Not tainted 5.0.0-rc8+ #9
      RIP: 0010:btrfs_set_item_key_safe+0x16c/0x180
      RSP: 0018:ffff976141257ab8 EFLAGS: 00010202
      RAX: 0000000000000001 RBX: ffff898a6b890930 RCX: 0000000004b70000
      RDX: 0000000000000000 RSI: ffff976141257bae RDI: ffff976141257acf
      RBP: ffff976141257b10 R08: 0000000000001000 R09: ffff9761412579a8
      R10: 0000000000000000 R11: 0000000000000000 R12: ffff976141257abe
      R13: 0000000000000003 R14: ffff898a6a8be578 R15: ffff976141257bae
      FS: 0000000000000000(0000) GS:ffff898a77a00000(0000) knlGS:0000000000000000
      CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      CR2: 00007f779d9cd624 CR3: 000000022b2b4006 CR4: 00000000000206f0
      Call Trace:
      truncate_one_csum+0xac/0xf0
      btrfs_del_csums+0x24f/0x3a0
      __btrfs_free_extent.isra.72+0x5a7/0xbe0
      __btrfs_run_delayed_refs+0x539/0x1120
      btrfs_run_delayed_refs+0xdb/0x1b0
      btrfs_commit_transaction+0x52/0x950
      ? start_transaction+0x94/0x450
      transaction_kthread+0x163/0x190
      kthread+0x105/0x140
      ? btrfs_cleanup_transaction+0x560/0x560
      ? kthread_destroy_worker+0x50/0x50
      ret_from_fork+0x35/0x40
      Modules linked in:
      ---[ end trace 93bf9db00e6c374e ]---
    
    [CAUSE]
    This crafted image has a tricky key order corruption:
    
      checksum tree key (CSUM_TREE ROOT_ITEM 0)
      node 29741056 level 1 items 14 free 107 generation 19 owner CSUM_TREE
              ...
              key (EXTENT_CSUM EXTENT_CSUM 73785344) block 29757440 gen 19
              key (EXTENT_CSUM EXTENT_CSUM 77594624) block 29753344 gen 19
              ...
    
      leaf 29757440 items 5 free space 150 generation 19 owner CSUM_TREE
              item 0 key (EXTENT_CSUM EXTENT_CSUM 73785344) itemoff 2323 itemsize 1672
                      range start 73785344 end 75497472 length 1712128
              item 1 key (EXTENT_CSUM EXTENT_CSUM 75497472) itemoff 2319 itemsize 4
                      range start 75497472 end 75501568 length 4096
              item 2 key (EXTENT_CSUM EXTENT_CSUM 75501568) itemoff 579 itemsize 1740
                      range start 75501568 end 77283328 length 1781760
              item 3 key (EXTENT_CSUM EXTENT_CSUM 77283328) itemoff 575 itemsize 4
                      range start 77283328 end 77287424 length 4096
              item 4 key (EXTENT_CSUM EXTENT_CSUM 4120596480) itemoff 275 itemsize 300 <<<
                      range start 4120596480 end 4120903680 length 307200
      leaf 29753344 items 3 free space 1936 generation 19 owner CSUM_TREE
              item 0 key (18446744073457893366 EXTENT_CSUM 77594624) itemoff 2323 itemsize 1672
                      range start 77594624 end 79306752 length 1712128
              ...
    
    Note the item 4 key of leaf 29757440, which is obviously too large, and
    even larger than the first key of the next leaf.
    
    However it still follows the key order in that tree block, thus tree
    checker is unable to detect it at read time, since tree checker can only
    work inside one leaf, thus such complex corruption can't be detected in
    advance.
    
    [FIX]
    The next time to detect such problem is at tree block merge time,
    which is in push_node_left(), balance_node_right(), push_leaf_left() or
    push_leaf_right().
    
    Now we check if the key order of the right-most key of the left node is
    larger than the left-most key of the right node.
    
    By this we don't need to call the full tree-checker, while still keeping
    the key order correct as key order in each node is already checked by
    tree checker thus we only need to check the above two slots.
    
    Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202833Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
    Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    d16c702f
ctree.c 143 KB