• Qu Wenruo's avatar
    btrfs: Handle owner mismatch gracefully when walking up tree · 65c6e82b
    Qu Wenruo authored
    When mounting certain crafted image, btrfs will trigger kernel BUG_ON()
    when trying to recover balance:
      kernel BUG at fs/btrfs/extent-tree.c:8956!
      invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
      CPU: 1 PID: 662 Comm: mount Not tainted 4.18.0-rc1-custom+ #10
      RIP: 0010:walk_up_proc+0x336/0x480 [btrfs]
      RSP: 0018:ffffb53540c9b890 EFLAGS: 00010202
      Call Trace:
       walk_up_tree+0x172/0x1f0 [btrfs]
       btrfs_drop_snapshot+0x3a4/0x830 [btrfs]
       merge_reloc_roots+0xe1/0x1d0 [btrfs]
       btrfs_recover_relocation+0x3ea/0x420 [btrfs]
       open_ctree+0x1af3/0x1dd0 [btrfs]
       btrfs_mount_root+0x66b/0x740 [btrfs]
       btrfs_mount+0x16d/0x890 [btrfs]
    Extent tree corruption.  In this particular case, reloc tree root's
    owner is DATA_RELOC_TREE (should be TREE_RELOC), thus its backref is
    corrupted and we failed the owner check in walk_up_tree().
    It's pretty hard to take care of every extent tree corruption, but at
    least we can remove such BUG_ON() and exit more gracefully.
    And since in this particular image, DATA_RELOC_TREE and TREE_RELOC share
    the same root (which is obviously invalid), we needs to make
    __del_reloc_root() more robust to detect such invalid sharing to avoid
    possible NULL dereference as root->node can be NULL in this case.
    Link: https://bugzilla.kernel.org/show_bug.cgi?id=200411
    Reported-by: default avatarXu Wen <wen.xu@gatech.edu>
    CC: stable@vger.kernel.org # 4.4+
    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>