1 /* 2 * Copyright (C) Qu Wenruo 2017. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public 14 * License along with this program. 15 */ 16 17 /* 18 * The module is used to catch unexpected/corrupted tree block data. 19 * Such behavior can be caused either by a fuzzed image or bugs. 20 * 21 * The objective is to do leaf/node validation checks when tree block is read 22 * from disk, and check *every* possible member, so other code won't 23 * need to checking them again. 24 * 25 * Due to the potential and unwanted damage, every checker needs to be 26 * carefully reviewed otherwise so it does not prevent mount of valid images. 27 */ 28 29 #include "ctree.h" 30 #include "tree-checker.h" 31 #include "disk-io.h" 32 #include "compression.h" 33 #include "hash.h" 34 35 /* 36 * Error message should follow the following format: 37 * corrupt <type>: <identifier>, <reason>[, <bad_value>] 38 * 39 * @type: leaf or node 40 * @identifier: the necessary info to locate the leaf/node. 41 * It's recommened to decode key.objecitd/offset if it's 42 * meaningful. 43 * @reason: describe the error 44 * @bad_value: optional, it's recommened to output bad value and its 45 * expected value (range). 46 * 47 * Since comma is used to separate the components, only space is allowed 48 * inside each component. 49 */ 50 51 /* 52 * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt. 53 * Allows callers to customize the output. 54 */ 55 __printf(4, 5) 56 static void generic_err(const struct btrfs_root *root, 57 const struct extent_buffer *eb, int slot, 58 const char *fmt, ...) 59 { 60 struct va_format vaf; 61 va_list args; 62 63 va_start(args, fmt); 64 65 vaf.fmt = fmt; 66 vaf.va = &args; 67 68 btrfs_crit(root->fs_info, 69 "corrupt %s: root=%llu block=%llu slot=%d, %pV", 70 btrfs_header_level(eb) == 0 ? "leaf" : "node", 71 root->objectid, btrfs_header_bytenr(eb), slot, &vaf); 72 va_end(args); 73 } 74 75 /* 76 * Customized reporter for extent data item, since its key objectid and 77 * offset has its own meaning. 78 */ 79 __printf(4, 5) 80 static void file_extent_err(const struct btrfs_root *root, 81 const struct extent_buffer *eb, int slot, 82 const char *fmt, ...) 83 { 84 struct btrfs_key key; 85 struct va_format vaf; 86 va_list args; 87 88 btrfs_item_key_to_cpu(eb, &key, slot); 89 va_start(args, fmt); 90 91 vaf.fmt = fmt; 92 vaf.va = &args; 93 94 btrfs_crit(root->fs_info, 95 "corrupt %s: root=%llu block=%llu slot=%d ino=%llu file_offset=%llu, %pV", 96 btrfs_header_level(eb) == 0 ? "leaf" : "node", root->objectid, 97 btrfs_header_bytenr(eb), slot, key.objectid, key.offset, &vaf); 98 va_end(args); 99 } 100 101 /* 102 * Return 0 if the btrfs_file_extent_##name is aligned to @alignment 103 * Else return 1 104 */ 105 #define CHECK_FE_ALIGNED(root, leaf, slot, fi, name, alignment) \ 106 ({ \ 107 if (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))) \ 108 file_extent_err((root), (leaf), (slot), \ 109 "invalid %s for file extent, have %llu, should be aligned to %u", \ 110 (#name), btrfs_file_extent_##name((leaf), (fi)), \ 111 (alignment)); \ 112 (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ 113 }) 114 115 static int check_extent_data_item(struct btrfs_root *root, 116 struct extent_buffer *leaf, 117 struct btrfs_key *key, int slot) 118 { 119 struct btrfs_file_extent_item *fi; 120 u32 sectorsize = root->fs_info->sectorsize; 121 u32 item_size = btrfs_item_size_nr(leaf, slot); 122 123 if (!IS_ALIGNED(key->offset, sectorsize)) { 124 file_extent_err(root, leaf, slot, 125 "unaligned file_offset for file extent, have %llu should be aligned to %u", 126 key->offset, sectorsize); 127 return -EUCLEAN; 128 } 129 130 fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); 131 132 if (btrfs_file_extent_type(leaf, fi) > BTRFS_FILE_EXTENT_TYPES) { 133 file_extent_err(root, leaf, slot, 134 "invalid type for file extent, have %u expect range [0, %u]", 135 btrfs_file_extent_type(leaf, fi), 136 BTRFS_FILE_EXTENT_TYPES); 137 return -EUCLEAN; 138 } 139 140 /* 141 * Support for new compression/encrption must introduce incompat flag, 142 * and must be caught in open_ctree(). 143 */ 144 if (btrfs_file_extent_compression(leaf, fi) > BTRFS_COMPRESS_TYPES) { 145 file_extent_err(root, leaf, slot, 146 "invalid compression for file extent, have %u expect range [0, %u]", 147 btrfs_file_extent_compression(leaf, fi), 148 BTRFS_COMPRESS_TYPES); 149 return -EUCLEAN; 150 } 151 if (btrfs_file_extent_encryption(leaf, fi)) { 152 file_extent_err(root, leaf, slot, 153 "invalid encryption for file extent, have %u expect 0", 154 btrfs_file_extent_encryption(leaf, fi)); 155 return -EUCLEAN; 156 } 157 if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { 158 /* Inline extent must have 0 as key offset */ 159 if (key->offset) { 160 file_extent_err(root, leaf, slot, 161 "invalid file_offset for inline file extent, have %llu expect 0", 162 key->offset); 163 return -EUCLEAN; 164 } 165 166 /* Compressed inline extent has no on-disk size, skip it */ 167 if (btrfs_file_extent_compression(leaf, fi) != 168 BTRFS_COMPRESS_NONE) 169 return 0; 170 171 /* Uncompressed inline extent size must match item size */ 172 if (item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + 173 btrfs_file_extent_ram_bytes(leaf, fi)) { 174 file_extent_err(root, leaf, slot, 175 "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", 176 item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + 177 btrfs_file_extent_ram_bytes(leaf, fi)); 178 return -EUCLEAN; 179 } 180 return 0; 181 } 182 183 /* Regular or preallocated extent has fixed item size */ 184 if (item_size != sizeof(*fi)) { 185 file_extent_err(root, leaf, slot, 186 "invalid item size for reg/prealloc file extent, have %u expect %zu", 187 item_size, sizeof(*fi)); 188 return -EUCLEAN; 189 } 190 if (CHECK_FE_ALIGNED(root, leaf, slot, fi, ram_bytes, sectorsize) || 191 CHECK_FE_ALIGNED(root, leaf, slot, fi, disk_bytenr, sectorsize) || 192 CHECK_FE_ALIGNED(root, leaf, slot, fi, disk_num_bytes, sectorsize) || 193 CHECK_FE_ALIGNED(root, leaf, slot, fi, offset, sectorsize) || 194 CHECK_FE_ALIGNED(root, leaf, slot, fi, num_bytes, sectorsize)) 195 return -EUCLEAN; 196 return 0; 197 } 198 199 static int check_csum_item(struct btrfs_root *root, struct extent_buffer *leaf, 200 struct btrfs_key *key, int slot) 201 { 202 u32 sectorsize = root->fs_info->sectorsize; 203 u32 csumsize = btrfs_super_csum_size(root->fs_info->super_copy); 204 205 if (key->objectid != BTRFS_EXTENT_CSUM_OBJECTID) { 206 generic_err(root, leaf, slot, 207 "invalid key objectid for csum item, have %llu expect %llu", 208 key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); 209 return -EUCLEAN; 210 } 211 if (!IS_ALIGNED(key->offset, sectorsize)) { 212 generic_err(root, leaf, slot, 213 "unaligned key offset for csum item, have %llu should be aligned to %u", 214 key->offset, sectorsize); 215 return -EUCLEAN; 216 } 217 if (!IS_ALIGNED(btrfs_item_size_nr(leaf, slot), csumsize)) { 218 generic_err(root, leaf, slot, 219 "unaligned item size for csum item, have %u should be aligned to %u", 220 btrfs_item_size_nr(leaf, slot), csumsize); 221 return -EUCLEAN; 222 } 223 return 0; 224 } 225 226 /* 227 * Customized reported for dir_item, only important new info is key->objectid, 228 * which represents inode number 229 */ 230 __printf(4, 5) 231 static void dir_item_err(const struct btrfs_root *root, 232 const struct extent_buffer *eb, int slot, 233 const char *fmt, ...) 234 { 235 struct btrfs_key key; 236 struct va_format vaf; 237 va_list args; 238 239 btrfs_item_key_to_cpu(eb, &key, slot); 240 va_start(args, fmt); 241 242 vaf.fmt = fmt; 243 vaf.va = &args; 244 245 btrfs_crit(root->fs_info, 246 "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", 247 btrfs_header_level(eb) == 0 ? "leaf" : "node", root->objectid, 248 btrfs_header_bytenr(eb), slot, key.objectid, &vaf); 249 va_end(args); 250 } 251 252 static int check_dir_item(struct btrfs_root *root, 253 struct extent_buffer *leaf, 254 struct btrfs_key *key, int slot) 255 { 256 struct btrfs_dir_item *di; 257 u32 item_size = btrfs_item_size_nr(leaf, slot); 258 u32 cur = 0; 259 260 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); 261 while (cur < item_size) { 262 u32 name_len; 263 u32 data_len; 264 u32 max_name_len; 265 u32 total_size; 266 u32 name_hash; 267 u8 dir_type; 268 269 /* header itself should not cross item boundary */ 270 if (cur + sizeof(*di) > item_size) { 271 dir_item_err(root, leaf, slot, 272 "dir item header crosses item boundary, have %zu boundary %u", 273 cur + sizeof(*di), item_size); 274 return -EUCLEAN; 275 } 276 277 /* dir type check */ 278 dir_type = btrfs_dir_type(leaf, di); 279 if (dir_type >= BTRFS_FT_MAX) { 280 dir_item_err(root, leaf, slot, 281 "invalid dir item type, have %u expect [0, %u)", 282 dir_type, BTRFS_FT_MAX); 283 return -EUCLEAN; 284 } 285 286 if (key->type == BTRFS_XATTR_ITEM_KEY && 287 dir_type != BTRFS_FT_XATTR) { 288 dir_item_err(root, leaf, slot, 289 "invalid dir item type for XATTR key, have %u expect %u", 290 dir_type, BTRFS_FT_XATTR); 291 return -EUCLEAN; 292 } 293 if (dir_type == BTRFS_FT_XATTR && 294 key->type != BTRFS_XATTR_ITEM_KEY) { 295 dir_item_err(root, leaf, slot, 296 "xattr dir type found for non-XATTR key"); 297 return -EUCLEAN; 298 } 299 if (dir_type == BTRFS_FT_XATTR) 300 max_name_len = XATTR_NAME_MAX; 301 else 302 max_name_len = BTRFS_NAME_LEN; 303 304 /* Name/data length check */ 305 name_len = btrfs_dir_name_len(leaf, di); 306 data_len = btrfs_dir_data_len(leaf, di); 307 if (name_len > max_name_len) { 308 dir_item_err(root, leaf, slot, 309 "dir item name len too long, have %u max %u", 310 name_len, max_name_len); 311 return -EUCLEAN; 312 } 313 if (name_len + data_len > BTRFS_MAX_XATTR_SIZE(root->fs_info)) { 314 dir_item_err(root, leaf, slot, 315 "dir item name and data len too long, have %u max %u", 316 name_len + data_len, 317 BTRFS_MAX_XATTR_SIZE(root->fs_info)); 318 return -EUCLEAN; 319 } 320 321 if (data_len && dir_type != BTRFS_FT_XATTR) { 322 dir_item_err(root, leaf, slot, 323 "dir item with invalid data len, have %u expect 0", 324 data_len); 325 return -EUCLEAN; 326 } 327 328 total_size = sizeof(*di) + name_len + data_len; 329 330 /* header and name/data should not cross item boundary */ 331 if (cur + total_size > item_size) { 332 dir_item_err(root, leaf, slot, 333 "dir item data crosses item boundary, have %u boundary %u", 334 cur + total_size, item_size); 335 return -EUCLEAN; 336 } 337 338 /* 339 * Special check for XATTR/DIR_ITEM, as key->offset is name 340 * hash, should match its name 341 */ 342 if (key->type == BTRFS_DIR_ITEM_KEY || 343 key->type == BTRFS_XATTR_ITEM_KEY) { 344 char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; 345 346 read_extent_buffer(leaf, namebuf, 347 (unsigned long)(di + 1), name_len); 348 name_hash = btrfs_name_hash(namebuf, name_len); 349 if (key->offset != name_hash) { 350 dir_item_err(root, leaf, slot, 351 "name hash mismatch with key, have 0x%016x expect 0x%016llx", 352 name_hash, key->offset); 353 return -EUCLEAN; 354 } 355 } 356 cur += total_size; 357 di = (struct btrfs_dir_item *)((void *)di + total_size); 358 } 359 return 0; 360 } 361 362 /* 363 * Common point to switch the item-specific validation. 364 */ 365 static int check_leaf_item(struct btrfs_root *root, 366 struct extent_buffer *leaf, 367 struct btrfs_key *key, int slot) 368 { 369 int ret = 0; 370 371 switch (key->type) { 372 case BTRFS_EXTENT_DATA_KEY: 373 ret = check_extent_data_item(root, leaf, key, slot); 374 break; 375 case BTRFS_EXTENT_CSUM_KEY: 376 ret = check_csum_item(root, leaf, key, slot); 377 break; 378 case BTRFS_DIR_ITEM_KEY: 379 case BTRFS_DIR_INDEX_KEY: 380 case BTRFS_XATTR_ITEM_KEY: 381 ret = check_dir_item(root, leaf, key, slot); 382 break; 383 } 384 return ret; 385 } 386 387 static int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf, 388 bool check_item_data) 389 { 390 struct btrfs_fs_info *fs_info = root->fs_info; 391 /* No valid key type is 0, so all key should be larger than this key */ 392 struct btrfs_key prev_key = {0, 0, 0}; 393 struct btrfs_key key; 394 u32 nritems = btrfs_header_nritems(leaf); 395 int slot; 396 397 /* 398 * Extent buffers from a relocation tree have a owner field that 399 * corresponds to the subvolume tree they are based on. So just from an 400 * extent buffer alone we can not find out what is the id of the 401 * corresponding subvolume tree, so we can not figure out if the extent 402 * buffer corresponds to the root of the relocation tree or not. So 403 * skip this check for relocation trees. 404 */ 405 if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { 406 struct btrfs_root *check_root; 407 408 key.objectid = btrfs_header_owner(leaf); 409 key.type = BTRFS_ROOT_ITEM_KEY; 410 key.offset = (u64)-1; 411 412 check_root = btrfs_get_fs_root(fs_info, &key, false); 413 /* 414 * The only reason we also check NULL here is that during 415 * open_ctree() some roots has not yet been set up. 416 */ 417 if (!IS_ERR_OR_NULL(check_root)) { 418 struct extent_buffer *eb; 419 420 eb = btrfs_root_node(check_root); 421 /* if leaf is the root, then it's fine */ 422 if (leaf != eb) { 423 generic_err(check_root, leaf, 0, 424 "invalid nritems, have %u should not be 0 for non-root leaf", 425 nritems); 426 free_extent_buffer(eb); 427 return -EUCLEAN; 428 } 429 free_extent_buffer(eb); 430 } 431 return 0; 432 } 433 434 if (nritems == 0) 435 return 0; 436 437 /* 438 * Check the following things to make sure this is a good leaf, and 439 * leaf users won't need to bother with similar sanity checks: 440 * 441 * 1) key ordering 442 * 2) item offset and size 443 * No overlap, no hole, all inside the leaf. 444 * 3) item content 445 * If possible, do comprehensive sanity check. 446 * NOTE: All checks must only rely on the item data itself. 447 */ 448 for (slot = 0; slot < nritems; slot++) { 449 u32 item_end_expected; 450 int ret; 451 452 btrfs_item_key_to_cpu(leaf, &key, slot); 453 454 /* Make sure the keys are in the right order */ 455 if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { 456 generic_err(root, leaf, slot, 457 "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", 458 prev_key.objectid, prev_key.type, 459 prev_key.offset, key.objectid, key.type, 460 key.offset); 461 return -EUCLEAN; 462 } 463 464 /* 465 * Make sure the offset and ends are right, remember that the 466 * item data starts at the end of the leaf and grows towards the 467 * front. 468 */ 469 if (slot == 0) 470 item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); 471 else 472 item_end_expected = btrfs_item_offset_nr(leaf, 473 slot - 1); 474 if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { 475 generic_err(root, leaf, slot, 476 "unexpected item end, have %u expect %u", 477 btrfs_item_end_nr(leaf, slot), 478 item_end_expected); 479 return -EUCLEAN; 480 } 481 482 /* 483 * Check to make sure that we don't point outside of the leaf, 484 * just in case all the items are consistent to each other, but 485 * all point outside of the leaf. 486 */ 487 if (btrfs_item_end_nr(leaf, slot) > 488 BTRFS_LEAF_DATA_SIZE(fs_info)) { 489 generic_err(root, leaf, slot, 490 "slot end outside of leaf, have %u expect range [0, %u]", 491 btrfs_item_end_nr(leaf, slot), 492 BTRFS_LEAF_DATA_SIZE(fs_info)); 493 return -EUCLEAN; 494 } 495 496 /* Also check if the item pointer overlaps with btrfs item. */ 497 if (btrfs_item_nr_offset(slot) + sizeof(struct btrfs_item) > 498 btrfs_item_ptr_offset(leaf, slot)) { 499 generic_err(root, leaf, slot, 500 "slot overlaps with its data, item end %lu data start %lu", 501 btrfs_item_nr_offset(slot) + 502 sizeof(struct btrfs_item), 503 btrfs_item_ptr_offset(leaf, slot)); 504 return -EUCLEAN; 505 } 506 507 if (check_item_data) { 508 /* 509 * Check if the item size and content meet other 510 * criteria 511 */ 512 ret = check_leaf_item(root, leaf, &key, slot); 513 if (ret < 0) 514 return ret; 515 } 516 517 prev_key.objectid = key.objectid; 518 prev_key.type = key.type; 519 prev_key.offset = key.offset; 520 } 521 522 return 0; 523 } 524 525 int btrfs_check_leaf_full(struct btrfs_root *root, struct extent_buffer *leaf) 526 { 527 return check_leaf(root, leaf, true); 528 } 529 530 int btrfs_check_leaf_relaxed(struct btrfs_root *root, 531 struct extent_buffer *leaf) 532 { 533 return check_leaf(root, leaf, false); 534 } 535 536 int btrfs_check_node(struct btrfs_root *root, struct extent_buffer *node) 537 { 538 unsigned long nr = btrfs_header_nritems(node); 539 struct btrfs_key key, next_key; 540 int slot; 541 u64 bytenr; 542 int ret = 0; 543 544 if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(root->fs_info)) { 545 btrfs_crit(root->fs_info, 546 "corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", 547 root->objectid, node->start, 548 nr == 0 ? "small" : "large", nr, 549 BTRFS_NODEPTRS_PER_BLOCK(root->fs_info)); 550 return -EUCLEAN; 551 } 552 553 for (slot = 0; slot < nr - 1; slot++) { 554 bytenr = btrfs_node_blockptr(node, slot); 555 btrfs_node_key_to_cpu(node, &key, slot); 556 btrfs_node_key_to_cpu(node, &next_key, slot + 1); 557 558 if (!bytenr) { 559 generic_err(root, node, slot, 560 "invalid NULL node pointer"); 561 ret = -EUCLEAN; 562 goto out; 563 } 564 if (!IS_ALIGNED(bytenr, root->fs_info->sectorsize)) { 565 generic_err(root, node, slot, 566 "unaligned pointer, have %llu should be aligned to %u", 567 bytenr, root->fs_info->sectorsize); 568 ret = -EUCLEAN; 569 goto out; 570 } 571 572 if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { 573 generic_err(root, node, slot, 574 "bad key order, current (%llu %u %llu) next (%llu %u %llu)", 575 key.objectid, key.type, key.offset, 576 next_key.objectid, next_key.type, 577 next_key.offset); 578 ret = -EUCLEAN; 579 goto out; 580 } 581 } 582 out: 583 return ret; 584 } 585