xref: /openbsd/sys/kern/subr_kubsan.c (revision 202e2461)
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
__ubsan_handle_add_overflow(struct overflow_data * data,unsigned long lhs,unsigned long rhs)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
__ubsan_handle_builtin_unreachable(struct unreachable_data * data)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
__ubsan_handle_divrem_overflow(struct overflow_data * data,unsigned long lhs,unsigned long rhs)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
__ubsan_handle_float_cast_overflow(struct float_cast_overflow_data * data,unsigned long val)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
__ubsan_handle_invalid_builtin(struct invalid_builtin_data * data)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
__ubsan_handle_load_invalid_value(struct invalid_value_data * data,unsigned long val)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
__ubsan_handle_nonnull_arg(struct nonnull_arg_data * data)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
__ubsan_handle_mul_overflow(struct overflow_data * data,unsigned long lhs,unsigned long rhs)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
__ubsan_handle_negate_overflow(struct overflow_data * data,unsigned long val)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
__ubsan_handle_out_of_bounds(struct out_of_bounds_data * data,unsigned long idx)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
__ubsan_handle_pointer_overflow(struct pointer_overflow_data * data,unsigned long base,unsigned long res)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
__ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data * data,unsigned long lhs,unsigned long rhs)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
__ubsan_handle_sub_overflow(struct overflow_data * data,unsigned long lhs,unsigned long rhs)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
__ubsan_handle_type_mismatch_v1(struct type_mismatch_data * data,unsigned long ptr)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
kubsan_init(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
kubsan_deserialize_int(struct type_descriptor * typ,unsigned long val)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
kubsan_deserialize_uint(struct type_descriptor * typ,unsigned long val)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
kubsan_defer_report(struct kubsan_report * kr)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
kubsan_format_int(struct type_descriptor * typ,unsigned long val,char * buf,size_t bufsiz)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
kubsan_format_location(const struct source_location * src,char * buf,size_t bufsiz)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
kubsan_is_reported(struct source_location * src)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 *
kubsan_kind(uint8_t kind)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
kubsan_report(void * arg)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
kubsan_unreport(struct source_location * src)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
is_negative(struct type_descriptor * typ,unsigned long val)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
is_shift_exponent_too_large(struct type_descriptor * typ,unsigned long val)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 *
pathstrip(const char * path)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