1 /* $OpenBSD: subr_kubsan.c,v 1.13 2024/09/06 13:31:59 mbuhl Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Anton Lindqvist <anton@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/param.h> 21 #include <sys/atomic.h> 22 #include <sys/syslimits.h> 23 #include <sys/systm.h> 24 #include <sys/timeout.h> 25 26 #include <uvm/uvm_extern.h> 27 28 #define KUBSAN_INTERVAL 100 /* report interval in msec */ 29 #define KUBSAN_NSLOTS 32 30 31 #define NUMBER_BUFSIZ 32 32 #define LOCATION_BUFSIZ (PATH_MAX + 32) /* filename:line:column */ 33 #define LOCATION_REPORTED (1U << 31) 34 35 #define NBITS(typ) (1 << ((typ)->t_info >> 1)) 36 #define SIGNED(typ) ((typ)->t_info & 1) 37 38 struct kubsan_report { 39 enum { 40 KUBSAN_FLOAT_CAST_OVERFLOW, 41 KUBSAN_INVALID_BUILTIN, 42 KUBSAN_INVALID_VALUE, 43 KUBSAN_NEGATE_OVERFLOW, 44 KUBSAN_NONNULL_ARG, 45 KUBSAN_OUT_OF_BOUNDS, 46 KUBSAN_OVERFLOW, 47 KUBSAN_POINTER_OVERFLOW, 48 KUBSAN_SHIFT_OUT_OF_BOUNDS, 49 KUBSAN_TYPE_MISMATCH, 50 KUBSAN_UNREACHABLE, 51 } kr_type; 52 53 struct source_location *kr_src; 54 55 union { 56 struct { 57 const struct float_cast_overflow_data *v_data; 58 unsigned long v_val; 59 } v_float_cast_overflow; 60 61 struct { 62 const struct invalid_builtin_data *v_data; 63 } v_invalid_builtin; 64 65 struct { 66 const struct invalid_value_data *v_data; 67 unsigned long v_val; 68 } v_invalid_value; 69 70 struct { 71 const struct overflow_data *v_data; 72 unsigned int v_val; 73 } v_negate_overflow; 74 75 struct { 76 const struct nonnull_arg_data *v_data; 77 } v_nonnull_arg; 78 79 struct { 80 const struct out_of_bounds_data *v_data; 81 unsigned int v_idx; 82 } v_out_of_bounds; 83 84 struct { 85 const struct overflow_data *v_data; 86 unsigned long v_lhs; 87 unsigned long v_rhs; 88 char v_op; 89 } v_overflow; 90 91 struct { 92 const struct pointer_overflow_data *v_data; 93 unsigned long v_base; 94 unsigned long v_res; 95 } v_pointer_overflow; 96 97 struct { 98 const struct shift_out_of_bounds_data *v_data; 99 unsigned long v_lhs; 100 unsigned long v_rhs; 101 } v_shift_out_of_bounds; 102 103 struct { 104 const struct type_mismatch_data *v_data; 105 unsigned long v_ptr; 106 } v_type_mismatch; 107 } kr_u; 108 }; 109 #define kr_float_cast_overflow kr_u.v_float_cast_overflow 110 #define kr_invalid_builtin kr_u.v_invalid_builtin 111 #define kr_invalid_value kr_u.v_invalid_value 112 #define kr_negate_overflow kr_u.v_negate_overflow 113 #define kr_nonnull_arg kr_u.v_nonnull_arg 114 #define kr_out_of_bounds kr_u.v_out_of_bounds 115 #define kr_overflow kr_u.v_overflow 116 #define kr_pointer_overflow kr_u.v_pointer_overflow 117 #define kr_shift_out_of_bounds kr_u.v_shift_out_of_bounds 118 #define kr_type_mismatch kr_u.v_type_mismatch 119 120 struct type_descriptor { 121 uint16_t t_kind; 122 uint16_t t_info; 123 char t_name[1]; /* type name as variable length array */ 124 }; 125 126 struct source_location { 127 const char *sl_filename; 128 uint32_t sl_line; 129 uint32_t sl_column; 130 }; 131 132 struct float_cast_overflow_data { 133 struct source_location d_src; 134 struct type_descriptor *d_ftype; /* from type */ 135 struct type_descriptor *d_ttype; /* to type */ 136 }; 137 138 struct invalid_builtin_data { 139 struct source_location d_src; 140 uint8_t d_kind; 141 }; 142 143 struct invalid_value_data { 144 struct source_location d_src; 145 struct type_descriptor *d_type; 146 }; 147 148 struct nonnull_arg_data { 149 struct source_location d_src; 150 struct source_location d_attr_src; /* __attribute__ location */ 151 int d_idx; 152 }; 153 154 struct out_of_bounds_data { 155 struct source_location d_src; 156 struct type_descriptor *d_atype; /* array type */ 157 struct type_descriptor *d_itype; /* index type */ 158 }; 159 160 struct overflow_data { 161 struct source_location d_src; 162 struct type_descriptor *d_type; 163 }; 164 165 struct pointer_overflow_data { 166 struct source_location d_src; 167 }; 168 169 struct shift_out_of_bounds_data { 170 struct source_location d_src; 171 struct type_descriptor *d_ltype; 172 struct type_descriptor *d_rtype; 173 }; 174 175 struct type_mismatch_data { 176 struct source_location d_src; 177 struct type_descriptor *d_type; 178 uint8_t d_align; /* log2 alignment */ 179 uint8_t d_kind; 180 }; 181 182 struct unreachable_data { 183 struct source_location d_src; 184 }; 185 186 int64_t kubsan_deserialize_int(struct type_descriptor *, 187 unsigned long); 188 uint64_t kubsan_deserialize_uint(struct type_descriptor *, 189 unsigned long); 190 void kubsan_defer_report(struct kubsan_report *); 191 void kubsan_format_int(struct type_descriptor *, unsigned long, 192 char *, size_t); 193 int kubsan_format_location(const struct source_location *, char *, 194 size_t); 195 int kubsan_is_reported(struct source_location *); 196 const char *kubsan_kind(uint8_t); 197 void kubsan_report(void *); 198 void kubsan_unreport(struct source_location *); 199 200 static int is_negative(struct type_descriptor *, unsigned long); 201 static int is_shift_exponent_too_large(struct type_descriptor *, 202 unsigned long); 203 204 static const char *pathstrip(const char *); 205 206 #ifdef KUBSAN_WATCH 207 int kubsan_watch = 2; 208 #else 209 int kubsan_watch = 1; 210 #endif 211 212 struct kubsan_report *kubsan_reports = NULL; 213 struct timeout kubsan_timo = TIMEOUT_INITIALIZER(kubsan_report, NULL); 214 unsigned int kubsan_slot = 0; 215 int kubsan_cold = 1; 216 217 /* 218 * Compiling the kernel with `-fsanitize=undefined' will cause the following 219 * functions to be called when a sanitizer detects undefined behavior. 220 * Some sanitizers are omitted since they are only applicable to C++. 221 * 222 * Every __ubsan_*() sanitizer function also has a corresponding 223 * __ubsan_*_abort() function as part of the ABI provided by Clang. 224 * But, since the kernel never is compiled with `fno-sanitize-recover' for 225 * obvious reasons, they are also omitted. 226 */ 227 228 void 229 __ubsan_handle_add_overflow(struct overflow_data *data, 230 unsigned long lhs, unsigned long rhs) 231 { 232 struct kubsan_report kr = { 233 .kr_type = KUBSAN_OVERFLOW, 234 .kr_src = &data->d_src, 235 .kr_overflow = { data, lhs, rhs, '+' }, 236 }; 237 238 kubsan_defer_report(&kr); 239 } 240 241 void 242 __ubsan_handle_builtin_unreachable(struct unreachable_data *data) 243 { 244 struct kubsan_report kr = { 245 .kr_type = KUBSAN_UNREACHABLE, 246 .kr_src = &data->d_src, 247 }; 248 249 kubsan_defer_report(&kr); 250 } 251 252 void 253 __ubsan_handle_divrem_overflow(struct overflow_data *data, 254 unsigned long lhs, unsigned long rhs) 255 { 256 struct kubsan_report kr = { 257 .kr_type = KUBSAN_OVERFLOW, 258 .kr_src = &data->d_src, 259 .kr_overflow = { data, lhs, rhs, '/' }, 260 }; 261 262 kubsan_defer_report(&kr); 263 } 264 265 void 266 __ubsan_handle_float_cast_overflow(struct float_cast_overflow_data *data, 267 unsigned long val) 268 { 269 struct kubsan_report kr = { 270 .kr_type = KUBSAN_FLOAT_CAST_OVERFLOW, 271 .kr_src = &data->d_src, 272 .kr_float_cast_overflow = { data, val }, 273 }; 274 275 kubsan_defer_report(&kr); 276 } 277 278 void 279 __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data) 280 { 281 struct kubsan_report kr = { 282 .kr_type = KUBSAN_INVALID_VALUE, 283 .kr_src = &data->d_src, 284 .kr_invalid_builtin = { data }, 285 }; 286 287 kubsan_defer_report(&kr); 288 } 289 290 void 291 __ubsan_handle_load_invalid_value(struct invalid_value_data *data, 292 unsigned long val) 293 { 294 struct kubsan_report kr = { 295 .kr_type = KUBSAN_INVALID_VALUE, 296 .kr_src = &data->d_src, 297 .kr_invalid_value = { data, val }, 298 }; 299 300 kubsan_defer_report(&kr); 301 } 302 303 void 304 __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data) 305 { 306 struct kubsan_report kr = { 307 .kr_type = KUBSAN_NONNULL_ARG, 308 .kr_src = &data->d_src, 309 .kr_nonnull_arg = { data }, 310 }; 311 312 kubsan_defer_report(&kr); 313 } 314 315 void 316 __ubsan_handle_mul_overflow(struct overflow_data *data, 317 unsigned long lhs, unsigned long rhs) 318 { 319 struct kubsan_report kr = { 320 .kr_type = KUBSAN_OVERFLOW, 321 .kr_src = &data->d_src, 322 .kr_overflow = { data, lhs, rhs, '*' }, 323 }; 324 325 kubsan_defer_report(&kr); 326 } 327 328 void 329 __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long val) 330 { 331 struct kubsan_report kr = { 332 .kr_type = KUBSAN_NEGATE_OVERFLOW, 333 .kr_src = &data->d_src, 334 .kr_negate_overflow = { data, val }, 335 }; 336 337 kubsan_defer_report(&kr); 338 } 339 340 void 341 __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, 342 unsigned long idx) 343 { 344 struct kubsan_report kr = { 345 .kr_type = KUBSAN_OUT_OF_BOUNDS, 346 .kr_src = &data->d_src, 347 .kr_out_of_bounds = { data, idx }, 348 }; 349 350 kubsan_defer_report(&kr); 351 } 352 353 void 354 __ubsan_handle_pointer_overflow(struct pointer_overflow_data *data, 355 unsigned long base, unsigned long res) 356 { 357 struct kubsan_report kr = { 358 .kr_type = KUBSAN_POINTER_OVERFLOW, 359 .kr_src = &data->d_src, 360 .kr_pointer_overflow = { data, base, res }, 361 }; 362 363 kubsan_defer_report(&kr); 364 } 365 366 void 367 __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, 368 unsigned long lhs, unsigned long rhs) 369 { 370 struct kubsan_report kr = { 371 .kr_type = KUBSAN_SHIFT_OUT_OF_BOUNDS, 372 .kr_src = &data->d_src, 373 .kr_shift_out_of_bounds = { data, lhs, rhs }, 374 }; 375 376 kubsan_defer_report(&kr); 377 } 378 379 void 380 __ubsan_handle_sub_overflow(struct overflow_data *data, 381 unsigned long lhs, unsigned long rhs) 382 { 383 struct kubsan_report kr = { 384 .kr_type = KUBSAN_OVERFLOW, 385 .kr_src = &data->d_src, 386 .kr_overflow = { data, lhs, rhs, '-' }, 387 }; 388 389 kubsan_defer_report(&kr); 390 } 391 392 void 393 __ubsan_handle_type_mismatch_v1(struct type_mismatch_data *data, 394 unsigned long ptr) 395 { 396 struct kubsan_report kr = { 397 .kr_type = KUBSAN_TYPE_MISMATCH, 398 .kr_src = &data->d_src, 399 .kr_type_mismatch = { data, ptr }, 400 }; 401 402 kubsan_defer_report(&kr); 403 } 404 405 /* 406 * Allocate storage for reports and schedule the reporter. 407 * Must be called as early on as possible in order to catch undefined behavior 408 * during boot. 409 */ 410 void 411 kubsan_init(void) 412 { 413 kubsan_reports = (void *)uvm_pageboot_alloc( 414 sizeof(struct kubsan_report) * KUBSAN_NSLOTS); 415 kubsan_cold = 0; 416 417 timeout_add_msec(&kubsan_timo, KUBSAN_INTERVAL); 418 } 419 420 int64_t 421 kubsan_deserialize_int(struct type_descriptor *typ, unsigned long val) 422 { 423 switch (NBITS(typ)) { 424 case 8: 425 return ((int8_t)val); 426 case 16: 427 return ((int16_t)val); 428 case 32: 429 return ((int32_t)val); 430 case 64: 431 default: 432 return ((int64_t)val); 433 } 434 } 435 436 uint64_t 437 kubsan_deserialize_uint(struct type_descriptor *typ, unsigned long val) 438 { 439 switch (NBITS(typ)) { 440 case 8: 441 return ((uint8_t)val); 442 case 16: 443 return ((uint16_t)val); 444 case 32: 445 return ((uint32_t)val); 446 case 64: 447 default: 448 return ((uint64_t)val); 449 } 450 } 451 452 void 453 kubsan_defer_report(struct kubsan_report *kr) 454 { 455 unsigned int slot; 456 457 if (__predict_false(kubsan_cold == 1) || 458 kubsan_is_reported(kr->kr_src)) 459 return; 460 461 slot = atomic_inc_int_nv(&kubsan_slot) - 1; 462 if (slot >= KUBSAN_NSLOTS) { 463 /* 464 * No slots left, flag source location as not reported and 465 * hope a slot will be available next time. 466 */ 467 kubsan_unreport(kr->kr_src); 468 return; 469 } 470 471 memcpy(&kubsan_reports[slot], kr, sizeof(*kr)); 472 } 473 474 void 475 kubsan_format_int(struct type_descriptor *typ, unsigned long val, 476 char *buf, size_t bufsiz) 477 { 478 switch (typ->t_kind) { 479 case 0: /* integer */ 480 if (SIGNED(typ)) { 481 int64_t i = kubsan_deserialize_int(typ, val); 482 snprintf(buf, bufsiz, "%lld", i); 483 } else { 484 uint64_t u = kubsan_deserialize_uint(typ, val); 485 snprintf(buf, bufsiz, "%llu", u); 486 } 487 break; 488 default: 489 snprintf(buf, bufsiz, "%#x<NaN>", typ->t_kind); 490 } 491 } 492 493 int 494 kubsan_format_location(const struct source_location *src, char *buf, 495 size_t bufsiz) 496 { 497 const char *path; 498 499 path = pathstrip(src->sl_filename); 500 501 return snprintf(buf, bufsiz, "%s:%u:%u", 502 path, src->sl_line & ~LOCATION_REPORTED, src->sl_column); 503 } 504 505 int 506 kubsan_is_reported(struct source_location *src) 507 { 508 uint32_t *line = &src->sl_line; 509 uint32_t prev; 510 511 /* 512 * Treat everything as reported when disabled. 513 * Otherwise, new violations would go by unnoticed. 514 */ 515 if (__predict_false(kubsan_watch == 0)) 516 return (1); 517 518 do { 519 prev = *line; 520 /* If already reported, avoid redundant atomic operation. */ 521 if (prev & LOCATION_REPORTED) 522 break; 523 } while (atomic_cas_uint(line, prev, prev | LOCATION_REPORTED) != prev); 524 525 return (prev & LOCATION_REPORTED); 526 } 527 528 const char * 529 kubsan_kind(uint8_t kind) 530 { 531 static const char *kinds[] = { 532 "load of", 533 "store to", 534 "reference binding to", 535 "member access within", 536 "member call on", 537 "constructor call on", 538 "downcast of", 539 "downcast of", 540 "upcast of", 541 "cast to virtual base of", 542 "_Nonnull binding to", 543 "dynamic operation on" 544 }; 545 546 if (kind >= nitems(kinds)) 547 return ("?"); 548 549 return (kinds[kind]); 550 } 551 552 void 553 kubsan_report(void *arg) 554 { 555 char bloc[LOCATION_BUFSIZ]; 556 char blhs[NUMBER_BUFSIZ]; 557 char brhs[NUMBER_BUFSIZ]; 558 struct kubsan_report *kr; 559 unsigned int nslots; 560 unsigned int i = 0; 561 562 again: 563 nslots = kubsan_slot; 564 if (nslots == 0) 565 goto done; 566 if (nslots > KUBSAN_NSLOTS) 567 nslots = KUBSAN_NSLOTS; 568 569 for (; i < nslots; i++) { 570 kr = &kubsan_reports[i]; 571 572 kubsan_format_location(kr->kr_src, bloc, sizeof(bloc)); 573 switch (kr->kr_type) { 574 case KUBSAN_FLOAT_CAST_OVERFLOW: { 575 const struct float_cast_overflow_data *data = 576 kr->kr_float_cast_overflow.v_data; 577 578 kubsan_format_int(data->d_ftype, 579 kr->kr_float_cast_overflow.v_val, 580 blhs, sizeof(blhs)); 581 printf("kubsan: %s: %s of type %s is outside the range " 582 "of representable values of type %s\n", 583 bloc, blhs, data->d_ftype->t_name, 584 data->d_ttype->t_name); 585 break; 586 } 587 588 case KUBSAN_INVALID_BUILTIN: { 589 const struct invalid_builtin_data *data = 590 kr->kr_invalid_builtin.v_data; 591 592 printf("kubsan: %s: invalid builtin: passing zero to " 593 "%s, which is not a valid argument\n", 594 bloc, kubsan_kind(data->d_kind)); 595 break; 596 } 597 598 case KUBSAN_INVALID_VALUE: { 599 const struct invalid_value_data *data = 600 kr->kr_invalid_value.v_data; 601 602 kubsan_format_int(data->d_type, 603 kr->kr_invalid_value.v_val, blhs, sizeof(blhs)); 604 printf("kubsan: %s: load invalid value: load of value " 605 "%s is not a valid value for type %s\n", 606 bloc, blhs, data->d_type->t_name); 607 break; 608 } 609 610 case KUBSAN_NEGATE_OVERFLOW: { 611 const struct overflow_data *data = 612 kr->kr_negate_overflow.v_data; 613 614 kubsan_format_int(data->d_type, 615 kr->kr_negate_overflow.v_val, blhs, sizeof(blhs)); 616 printf("kubsan: %s: negate overflow: negation of %s " 617 "cannot be represented in type %s\n", 618 bloc, blhs, data->d_type->t_name); 619 break; 620 } 621 622 case KUBSAN_NONNULL_ARG: { 623 const struct nonnull_arg_data *data = 624 kr->kr_nonnull_arg.v_data; 625 626 if (data->d_attr_src.sl_filename) 627 kubsan_format_location(&data->d_attr_src, 628 blhs, sizeof(blhs)); 629 else 630 blhs[0] = '\0'; 631 632 printf("kubsan: %s: null pointer passed as argument " 633 "%d, which is declared to never be null%s%s\n", 634 bloc, data->d_idx, 635 blhs[0] ? "nonnull specified in " : "", blhs); 636 break; 637 } 638 639 case KUBSAN_OUT_OF_BOUNDS: { 640 const struct out_of_bounds_data *data = 641 kr->kr_out_of_bounds.v_data; 642 643 kubsan_format_int(data->d_itype, 644 kr->kr_out_of_bounds.v_idx, blhs, sizeof(blhs)); 645 printf("kubsan: %s: out of bounds: index %s is out of " 646 "range for type %s\n", 647 bloc, blhs, data->d_atype->t_name); 648 break; 649 } 650 651 case KUBSAN_OVERFLOW: { 652 const struct overflow_data *data = 653 kr->kr_overflow.v_data; 654 655 kubsan_format_int(data->d_type, 656 kr->kr_overflow.v_lhs, blhs, sizeof(blhs)); 657 kubsan_format_int(data->d_type, 658 kr->kr_overflow.v_rhs, brhs, sizeof(brhs)); 659 printf("kubsan: %s: %s integer overflow: %s %c %s " 660 "cannot be represented in type %s\n", 661 bloc, SIGNED(data->d_type) ? "signed" : "unsigned", 662 blhs, kr->kr_overflow.v_op, brhs, 663 data->d_type->t_name); 664 break; 665 } 666 667 case KUBSAN_POINTER_OVERFLOW: 668 printf("kubsan: %s: pointer overflow: pointer " 669 "expression with base %#lx overflowed to %#lx\n", 670 bloc, kr->kr_pointer_overflow.v_base, 671 kr->kr_pointer_overflow.v_res); 672 break; 673 674 case KUBSAN_SHIFT_OUT_OF_BOUNDS: { 675 const struct shift_out_of_bounds_data *data = 676 kr->kr_shift_out_of_bounds.v_data; 677 unsigned long lhs = kr->kr_shift_out_of_bounds.v_lhs; 678 unsigned long rhs = kr->kr_shift_out_of_bounds.v_rhs; 679 680 kubsan_format_int(data->d_ltype, lhs, blhs, 681 sizeof(blhs)); 682 kubsan_format_int(data->d_rtype, rhs, brhs, 683 sizeof(brhs)); 684 if (is_negative(data->d_rtype, rhs)) 685 printf("kubsan: %s: shift: shift exponent %s " 686 "is negative\n", 687 bloc, brhs); 688 else if (is_shift_exponent_too_large(data->d_rtype, rhs)) 689 printf("kubsan: %s: shift: shift exponent %s " 690 "is too large for %u-bit type\n", 691 bloc, brhs, NBITS(data->d_rtype)); 692 else if (is_negative(data->d_ltype, lhs)) 693 printf("kubsan: %s: shift: left shift of " 694 "negative value %s\n", 695 bloc, blhs); 696 else 697 printf("kubsan: %s: shift: left shift of %s by " 698 "%s places cannot be represented in type " 699 "%s\n", 700 bloc, blhs, brhs, data->d_ltype->t_name); 701 break; 702 } 703 704 case KUBSAN_TYPE_MISMATCH: { 705 const struct type_mismatch_data *data = 706 kr->kr_type_mismatch.v_data; 707 unsigned long ptr = kr->kr_type_mismatch.v_ptr; 708 unsigned long align = 1UL << data->d_align; 709 710 if (ptr == 0UL) 711 printf("kubsan: %s: type mismatch: %s null " 712 "pointer of type %s\n", 713 bloc, kubsan_kind(data->d_kind), 714 data->d_type->t_name); 715 else if (ptr & (align - 1)) 716 printf("kubsan: %s: type mismatch: %s " 717 "misaligned address %p for type %s which " 718 "requires %lu byte alignment\n", 719 bloc, kubsan_kind(data->d_kind), 720 (void *)ptr, data->d_type->t_name, align); 721 else 722 printf("kubsan: %s: type mismatch: %s address " 723 "%p with insufficient space for an object " 724 "of type %s\n", 725 bloc, kubsan_kind(data->d_kind), 726 (void *)ptr, data->d_type->t_name); 727 break; 728 } 729 730 case KUBSAN_UNREACHABLE: 731 printf("kubsan: %s: unreachable: calling " 732 "__builtin_unreachable()\n", 733 bloc); 734 break; 735 } 736 737 #ifdef DDB 738 if (kubsan_watch == 2) 739 db_enter(); 740 #endif 741 } 742 743 /* New reports can arrive at any time. */ 744 if (atomic_cas_uint(&kubsan_slot, nslots, 0) != nslots) { 745 if (nslots < KUBSAN_NSLOTS) 746 goto again; 747 atomic_swap_uint(&kubsan_slot, 0); 748 } 749 750 done: 751 timeout_add_msec(&kubsan_timo, KUBSAN_INTERVAL); 752 } 753 754 void 755 kubsan_unreport(struct source_location *src) 756 { 757 uint32_t *line = &src->sl_line; 758 759 atomic_clearbits_int(line, LOCATION_REPORTED); 760 } 761 762 static int 763 is_negative(struct type_descriptor *typ, unsigned long val) 764 { 765 return (SIGNED(typ) && kubsan_deserialize_int(typ, val) < 0); 766 } 767 768 static int 769 is_shift_exponent_too_large(struct type_descriptor *typ, unsigned long val) 770 { 771 return (kubsan_deserialize_int(typ, val) >= NBITS(typ)); 772 } 773 774 /* 775 * A source location is an absolute path making reports quite long. 776 * Instead, use everything after the first /sys/ segment as the path. 777 */ 778 static const char * 779 pathstrip(const char *path) 780 { 781 const char *needle = "/sys/"; 782 size_t i, j; 783 784 for (i = j = 0; path[i] != '\0'; i++) { 785 if (path[i] != needle[j]) { 786 j = 0; 787 continue; 788 } 789 790 if (needle[++j] == '\0') 791 return path + i + 1; 792 } 793 794 return path; 795 } 796