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