summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-checker.c
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2019-07-16 05:00:34 -0400
committerDavid Sterba <dsterba@suse.com>2019-09-09 08:59:01 -0400
commit259ee7754b6793af8bdd77f9ca818bc41cfe9541 (patch)
tree1df9c3d63c8245a1577e546e6c789faf1baba30d /fs/btrfs/tree-checker.c
parent2a28468e525f3924efed7f29f2bc5a2926e7e19a (diff)
btrfs: tree-checker: Add ROOT_ITEM check
This patch will introduce ROOT_ITEM check, which includes: - Key->objectid and key->offset check Currently only some easy check, e.g. 0 as rootid is invalid. - Item size check Root item size is fixed. - Generation checks Generation, generation_v2 and last_snapshot should not be greater than super generation + 1 - Level and alignment check Level should be in [0, 7], and bytenr must be aligned to sector size. - Flags check Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203261 Reported-by: Jungyeon Yoon <jungyeon.yoon@gmail.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/tree-checker.c')
-rw-r--r--fs/btrfs/tree-checker.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index ccd5706199d7..d83adda6c090 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -821,6 +821,95 @@ static int check_inode_item(struct extent_buffer *leaf,
821 return 0; 821 return 0;
822} 822}
823 823
824static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key,
825 int slot)
826{
827 struct btrfs_fs_info *fs_info = leaf->fs_info;
828 struct btrfs_root_item ri;
829 const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY |
830 BTRFS_ROOT_SUBVOL_DEAD;
831
832 /* No such tree id */
833 if (key->objectid == 0) {
834 generic_err(leaf, slot, "invalid root id 0");
835 return -EUCLEAN;
836 }
837
838 /*
839 * Some older kernel may create ROOT_ITEM with non-zero offset, so here
840 * we only check offset for reloc tree whose key->offset must be a
841 * valid tree.
842 */
843 if (key->objectid == BTRFS_TREE_RELOC_OBJECTID && key->offset == 0) {
844 generic_err(leaf, slot, "invalid root id 0 for reloc tree");
845 return -EUCLEAN;
846 }
847
848 if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) {
849 generic_err(leaf, slot,
850 "invalid root item size, have %u expect %zu",
851 btrfs_item_size_nr(leaf, slot), sizeof(ri));
852 }
853
854 read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot),
855 sizeof(ri));
856
857 /* Generation related */
858 if (btrfs_root_generation(&ri) >
859 btrfs_super_generation(fs_info->super_copy) + 1) {
860 generic_err(leaf, slot,
861 "invalid root generation, have %llu expect (0, %llu]",
862 btrfs_root_generation(&ri),
863 btrfs_super_generation(fs_info->super_copy) + 1);
864 return -EUCLEAN;
865 }
866 if (btrfs_root_generation_v2(&ri) >
867 btrfs_super_generation(fs_info->super_copy) + 1) {
868 generic_err(leaf, slot,
869 "invalid root v2 generation, have %llu expect (0, %llu]",
870 btrfs_root_generation_v2(&ri),
871 btrfs_super_generation(fs_info->super_copy) + 1);
872 return -EUCLEAN;
873 }
874 if (btrfs_root_last_snapshot(&ri) >
875 btrfs_super_generation(fs_info->super_copy) + 1) {
876 generic_err(leaf, slot,
877 "invalid root last_snapshot, have %llu expect (0, %llu]",
878 btrfs_root_last_snapshot(&ri),
879 btrfs_super_generation(fs_info->super_copy) + 1);
880 return -EUCLEAN;
881 }
882
883 /* Alignment and level check */
884 if (!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize)) {
885 generic_err(leaf, slot,
886 "invalid root bytenr, have %llu expect to be aligned to %u",
887 btrfs_root_bytenr(&ri), fs_info->sectorsize);
888 return -EUCLEAN;
889 }
890 if (btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL) {
891 generic_err(leaf, slot,
892 "invalid root level, have %u expect [0, %u]",
893 btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1);
894 return -EUCLEAN;
895 }
896 if (ri.drop_level >= BTRFS_MAX_LEVEL) {
897 generic_err(leaf, slot,
898 "invalid root level, have %u expect [0, %u]",
899 ri.drop_level, BTRFS_MAX_LEVEL - 1);
900 return -EUCLEAN;
901 }
902
903 /* Flags check */
904 if (btrfs_root_flags(&ri) & ~valid_root_flags) {
905 generic_err(leaf, slot,
906 "invalid root flags, have 0x%llx expect mask 0x%llx",
907 btrfs_root_flags(&ri), valid_root_flags);
908 return -EUCLEAN;
909 }
910 return 0;
911}
912
824/* 913/*
825 * Common point to switch the item-specific validation. 914 * Common point to switch the item-specific validation.
826 */ 915 */
@@ -856,6 +945,9 @@ static int check_leaf_item(struct extent_buffer *leaf,
856 case BTRFS_INODE_ITEM_KEY: 945 case BTRFS_INODE_ITEM_KEY:
857 ret = check_inode_item(leaf, key, slot); 946 ret = check_inode_item(leaf, key, slot);
858 break; 947 break;
948 case BTRFS_ROOT_ITEM_KEY:
949 ret = check_root_item(leaf, key, slot);
950 break;
859 } 951 }
860 return ret; 952 return ret;
861} 953}