FreeBSD kernel kern code
subr_msan.c
Go to the documentation of this file.
1/* $NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $ */
2
3/*
4 * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net
5 * All rights reserved.
6 * Copyright (c) 2021 The FreeBSD Foundation
7 *
8 * Portions of this software were developed by Mark Johnston under sponsorship
9 * from the FreeBSD Foundation.
10 *
11 * This code is part of the KMSAN subsystem of the NetBSD kernel.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#define SAN_RUNTIME
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD$");
39#if 0
40__KERNEL_RCSID(0, "$NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $");
41#endif
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/bio.h>
46#include <sys/buf.h>
47#include <sys/conf.h>
48#include <sys/kdb.h>
49#include <sys/kernel.h>
50#include <sys/linker.h>
51#include <sys/malloc.h>
52#include <sys/mbuf.h>
53#include <sys/memdesc.h>
54#include <sys/msan.h>
55#include <sys/proc.h>
56#include <sys/stack.h>
57#include <sys/sysctl.h>
58#include <sys/uio.h>
59
60#include <cam/cam.h>
61#include <cam/cam_ccb.h>
62
63#include <vm/vm.h>
64#include <vm/pmap.h>
65
66#include <machine/msan.h>
67#include <machine/stdarg.h>
68
69void kmsan_init_arg(size_t);
70void kmsan_init_ret(size_t);
71
72/* -------------------------------------------------------------------------- */
73
74/*
75 * Part of the compiler ABI.
76 */
77
78typedef struct {
79 uint8_t *shad;
80 msan_orig_t *orig;
82
83#define MSAN_PARAM_SIZE 800
84#define MSAN_RETVAL_SIZE 800
85typedef struct {
86 uint8_t param_shadow[MSAN_PARAM_SIZE];
87 uint8_t retval_shadow[MSAN_RETVAL_SIZE];
88 uint8_t va_arg_shadow[MSAN_PARAM_SIZE];
89 uint8_t va_arg_origin[MSAN_PARAM_SIZE];
91 msan_orig_t param_origin[MSAN_PARAM_SIZE / sizeof(msan_orig_t)];
92 msan_orig_t retval_origin;
94
95/* -------------------------------------------------------------------------- */
96
97#define MSAN_NCONTEXT 4
98#define MSAN_ORIG_MASK (~0x3)
99
100typedef struct kmsan_td {
101 size_t ctx;
104
106
107/*
108 * Use separate dummy regions for loads and stores: stores may mark the region
109 * as uninitialized, and that can trigger false positives.
110 */
111static uint8_t msan_dummy_shad[PAGE_SIZE] __aligned(PAGE_SIZE);
112static uint8_t msan_dummy_write_shad[PAGE_SIZE] __aligned(PAGE_SIZE);
113static uint8_t msan_dummy_orig[PAGE_SIZE] __aligned(PAGE_SIZE);
115static bool kmsan_enabled __read_mostly;
116
117static bool kmsan_reporting = false;
118
119/*
120 * Avoid clobbering any thread-local state before we panic.
121 */
122#define kmsan_panic(f, ...) do { \
123 kmsan_enabled = false; \
124 panic(f, __VA_ARGS__); \
125} while (0)
126
127#define REPORT(f, ...) do { \
128 if (panic_on_violation) { \
129 kmsan_panic(f, __VA_ARGS__); \
130 } else { \
131 struct stack st; \
132 \
133 stack_save(&st); \
134 printf(f "\n", __VA_ARGS__); \
135 stack_print_ddb(&st); \
136 } \
137} while (0)
138
139FEATURE(kmsan, "Kernel memory sanitizer");
140
141static SYSCTL_NODE(_debug, OID_AUTO, kmsan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
142 "KMSAN options");
143
144static bool panic_on_violation = 1;
145SYSCTL_BOOL(_debug_kmsan, OID_AUTO, panic_on_violation, CTLFLAG_RWTUN,
147 "Panic if an invalid access is detected");
148
149static MALLOC_DEFINE(M_KMSAN, "kmsan", "Kernel memory sanitizer");
150
151/* -------------------------------------------------------------------------- */
152
153static inline const char *
155{
156 switch (type) {
157 case KMSAN_TYPE_STACK:
158 return ("stack");
159 case KMSAN_TYPE_KMEM:
160 return ("kmem");
161 case KMSAN_TYPE_MALLOC:
162 return ("malloc");
163 case KMSAN_TYPE_UMA:
164 return ("UMA");
165 default:
166 return ("unknown");
167 }
168}
169
170static void
171kmsan_report_hook(const void *addr, size_t size, size_t off, const char *hook)
172{
173 msan_orig_t *orig;
174 const char *typename;
175 char *var, *fn;
176 uintptr_t ptr;
177 long foff;
178 char buf[128];
179 int type;
180
181 if (__predict_false(panicstr != NULL || kdb_active || kmsan_reporting))
182 return;
183
184 kmsan_reporting = true;
185 __compiler_membar();
186
187 orig = (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
188 orig = (msan_orig_t *)((uintptr_t)orig & MSAN_ORIG_MASK);
189
190 if (*orig == 0) {
191 REPORT("MSan: Uninitialized memory in %s, offset %zu",
192 hook, off);
193 goto out;
194 }
195
196 kmsan_md_orig_decode(*orig, &type, &ptr);
197 typename = kmsan_orig_name(type);
198
199 if (linker_ddb_search_symbol_name((caddr_t)ptr, buf,
200 sizeof(buf), &foff) == 0) {
201 REPORT("MSan: Uninitialized %s memory in %s, "
202 "offset %zu/%zu, addr %p, from %s+%#lx",
203 typename, hook, off, size, addr, buf, foff);
204 } else if (__builtin_memcmp((void *)ptr, "----", 4) == 0) {
205 /*
206 * The format of the string is: "----var@function". Parse it to
207 * display a nice warning.
208 */
209 var = (char *)ptr + 4;
210 strlcpy(buf, var, sizeof(buf));
211 var = buf;
212 fn = strchr(buf, '@');
213 *fn++ = '\0';
214 REPORT("MSan: Uninitialized %s memory in %s, offset %zu, "
215 "variable '%s' from %s", typename, hook, off, var, fn);
216 } else {
217 REPORT("MSan: Uninitialized %s memory in %s, "
218 "offset %zu/%zu, addr %p, PC %p",
219 typename, hook, off, size, addr, (void *)ptr);
220 }
221
222out:
223 __compiler_membar();
224 kmsan_reporting = false;
225}
226
227static void
228kmsan_report_inline(msan_orig_t orig, unsigned long pc)
229{
230 const char *typename;
231 char *var, *fn;
232 uintptr_t ptr;
233 char buf[128];
234 long foff;
235 int type;
236
237 if (__predict_false(panicstr != NULL || kdb_active || kmsan_reporting))
238 return;
239
240 kmsan_reporting = true;
241 __compiler_membar();
242
243 if (orig == 0) {
244 REPORT("MSan: uninitialized variable in %p", (void *)pc);
245 goto out;
246 }
247
248 kmsan_md_orig_decode(orig, &type, &ptr);
249 typename = kmsan_orig_name(type);
250
251 if (linker_ddb_search_symbol_name((caddr_t)ptr, buf,
252 sizeof(buf), &foff) == 0) {
253 REPORT("MSan: Uninitialized %s memory from %s+%#lx",
254 typename, buf, foff);
255 } else if (__builtin_memcmp((void *)ptr, "----", 4) == 0) {
256 /*
257 * The format of the string is: "----var@function". Parse it to
258 * display a nice warning.
259 */
260 var = (char *)ptr + 4;
261 strlcpy(buf, var, sizeof(buf));
262 var = buf;
263 fn = strchr(buf, '@');
264 *fn++ = '\0';
265 REPORT("MSan: Uninitialized variable '%s' from %s", var, fn);
266 } else {
267 REPORT("MSan: Uninitialized %s memory, origin %x",
268 typename, orig);
269 }
270
271out:
272 __compiler_membar();
273 kmsan_reporting = false;
274}
275
276/* -------------------------------------------------------------------------- */
277
278static inline msan_meta_t
279kmsan_meta_get(const void *addr, size_t size, const bool write)
280{
281 msan_meta_t ret;
282
283 if (__predict_false(!kmsan_enabled)) {
284 ret.shad = write ? msan_dummy_write_shad : msan_dummy_shad;
285 ret.orig = (msan_orig_t *)msan_dummy_orig;
286 } else if (__predict_false(kmsan_md_unsupported((vm_offset_t)addr))) {
287 ret.shad = write ? msan_dummy_write_shad : msan_dummy_shad;
288 ret.orig = (msan_orig_t *)msan_dummy_orig;
289 } else {
290 ret.shad = (void *)kmsan_md_addr_to_shad((vm_offset_t)addr);
291 ret.orig =
292 (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
293 ret.orig = (msan_orig_t *)((uintptr_t)ret.orig &
295 }
296
297 return (ret);
298}
299
300static inline void
301kmsan_origin_fill(const void *addr, msan_orig_t o, size_t size)
302{
303 msan_orig_t *orig;
304 size_t i;
305
306 if (__predict_false(!kmsan_enabled))
307 return;
308 if (__predict_false(kmsan_md_unsupported((vm_offset_t)addr)))
309 return;
310
311 orig = (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
312 size += ((uintptr_t)orig & (sizeof(*orig) - 1));
313 orig = (msan_orig_t *)((uintptr_t)orig & MSAN_ORIG_MASK);
314
315 for (i = 0; i < size; i += 4) {
316 orig[i / 4] = o;
317 }
318}
319
320static inline void
321kmsan_shadow_fill(uintptr_t addr, uint8_t c, size_t size)
322{
323 uint8_t *shad;
324
325 if (__predict_false(!kmsan_enabled))
326 return;
327 if (__predict_false(kmsan_md_unsupported(addr)))
328 return;
329
330 shad = (uint8_t *)kmsan_md_addr_to_shad(addr);
331 __builtin_memset(shad, c, size);
332}
333
334static inline void
335kmsan_meta_copy(void *dst, const void *src, size_t size)
336{
337 uint8_t *orig_src, *orig_dst;
338 uint8_t *shad_src, *shad_dst;
339 msan_orig_t *_src, *_dst;
340 size_t i;
341
342 if (__predict_false(!kmsan_enabled))
343 return;
344 if (__predict_false(kmsan_md_unsupported((vm_offset_t)dst)))
345 return;
346 if (__predict_false(kmsan_md_unsupported((vm_offset_t)src))) {
347 kmsan_shadow_fill((uintptr_t)dst, KMSAN_STATE_INITED, size);
348 return;
349 }
350
351 shad_src = (uint8_t *)kmsan_md_addr_to_shad((vm_offset_t)src);
352 shad_dst = (uint8_t *)kmsan_md_addr_to_shad((vm_offset_t)dst);
353 __builtin_memmove(shad_dst, shad_src, size);
354
355 orig_src = (uint8_t *)kmsan_md_addr_to_orig((vm_offset_t)src);
356 orig_dst = (uint8_t *)kmsan_md_addr_to_orig((vm_offset_t)dst);
357 for (i = 0; i < size; i++) {
358 _src = (msan_orig_t *)((uintptr_t)orig_src & MSAN_ORIG_MASK);
359 _dst = (msan_orig_t *)((uintptr_t)orig_dst & MSAN_ORIG_MASK);
360 *_dst = *_src;
361 orig_src++;
362 orig_dst++;
363 }
364}
365
366static inline void
367kmsan_shadow_check(uintptr_t addr, size_t size, const char *hook)
368{
369 uint8_t *shad;
370 size_t i;
371
372 if (__predict_false(!kmsan_enabled))
373 return;
374 if (__predict_false(kmsan_md_unsupported(addr)))
375 return;
376
377 shad = (uint8_t *)kmsan_md_addr_to_shad(addr);
378 for (i = 0; i < size; i++) {
379 if (__predict_true(shad[i] == 0))
380 continue;
381 kmsan_report_hook((const char *)addr + i, size, i, hook);
382 break;
383 }
384}
385
386void
388{
389 msan_td_t *mtd;
390 uint8_t *arg;
391
392 if (__predict_false(!kmsan_enabled))
393 return;
394 if (__predict_false(curthread == NULL))
395 return;
396 mtd = curthread->td_kmsan;
397 arg = mtd->tls[mtd->ctx].param_shadow;
398 __builtin_memset(arg, 0, n);
399}
400
401void
403{
404 msan_td_t *mtd;
405 uint8_t *arg;
406
407 if (__predict_false(!kmsan_enabled))
408 return;
409 if (__predict_false(curthread == NULL))
410 return;
411 mtd = curthread->td_kmsan;
412 arg = mtd->tls[mtd->ctx].retval_shadow;
413 __builtin_memset(arg, 0, n);
414}
415
416static void
417kmsan_check_arg(size_t size, const char *hook)
418{
419 msan_td_t *mtd;
420 uint8_t *arg;
421 size_t i;
422
423 if (__predict_false(!kmsan_enabled))
424 return;
425 if (__predict_false(curthread == NULL))
426 return;
427 mtd = curthread->td_kmsan;
428 arg = mtd->tls[mtd->ctx].param_shadow;
429
430 for (i = 0; i < size; i++) {
431 if (__predict_true(arg[i] == 0))
432 continue;
433 kmsan_report_hook((const char *)arg + i, size, i, hook);
434 break;
435 }
436}
437
438void
439kmsan_thread_alloc(struct thread *td)
440{
441 msan_td_t *mtd;
442
443 if (!kmsan_enabled)
444 return;
445
446 mtd = td->td_kmsan;
447 if (mtd == NULL) {
448 /* We might be recycling a thread. */
449 kmsan_init_arg(sizeof(size_t) + sizeof(struct malloc_type *) +
450 sizeof(int));
451 mtd = malloc(sizeof(*mtd), M_KMSAN, M_WAITOK);
452 }
453 kmsan_memset(mtd, 0, sizeof(*mtd));
454 mtd->ctx = 0;
455
456 if (td->td_kstack != 0)
457 kmsan_mark((void *)td->td_kstack, ptoa(td->td_kstack_pages),
458 KMSAN_STATE_UNINIT);
459
460 td->td_kmsan = mtd;
461}
462
463void
464kmsan_thread_free(struct thread *td)
465{
466 msan_td_t *mtd;
467
468 if (!kmsan_enabled)
469 return;
470 if (__predict_false(td == curthread))
471 kmsan_panic("%s: freeing KMSAN TLS for curthread", __func__);
472
473 mtd = td->td_kmsan;
474 kmsan_init_arg(sizeof(void *) + sizeof(struct malloc_type *));
475 free(mtd, M_KMSAN);
476 td->td_kmsan = NULL;
477}
478
479void kmsan_intr_enter(void);
480void kmsan_intr_leave(void);
481
482void
484{
485 msan_td_t *mtd;
486
487 if (__predict_false(!kmsan_enabled))
488 return;
489
490 mtd = curthread->td_kmsan;
491 mtd->ctx++;
492 if (__predict_false(mtd->ctx >= MSAN_NCONTEXT))
493 kmsan_panic("%s: mtd->ctx = %zu", __func__, mtd->ctx);
494}
495
496void
498{
499 msan_td_t *mtd;
500
501 if (__predict_false(!kmsan_enabled))
502 return;
503
504 mtd = curthread->td_kmsan;
505 if (__predict_false(mtd->ctx == 0))
506 kmsan_panic("%s: mtd->ctx = %zu", __func__, mtd->ctx);
507 mtd->ctx--;
508}
509
510/* -------------------------------------------------------------------------- */
511
512void
513kmsan_shadow_map(vm_offset_t addr, size_t size)
514{
515 size_t npages, i;
516 vm_offset_t va;
517
518 MPASS(addr % PAGE_SIZE == 0);
519 MPASS(size % PAGE_SIZE == 0);
520
521 if (!kmsan_enabled)
522 return;
523
524 npages = atop(size);
525
526 va = kmsan_md_addr_to_shad(addr);
527 for (i = 0; i < npages; i++) {
528 pmap_san_enter(va + ptoa(i));
529 }
530
531 va = kmsan_md_addr_to_orig(addr);
532 for (i = 0; i < npages; i++) {
533 pmap_san_enter(va + ptoa(i));
534 }
535}
536
537void
538kmsan_orig(const void *addr, size_t size, int type, uintptr_t pc)
539{
540 msan_orig_t orig;
541
542 orig = kmsan_md_orig_encode(type, pc);
543 kmsan_origin_fill(addr, orig, size);
544}
545
546void
547kmsan_mark(const void *addr, size_t size, uint8_t c)
548{
549 kmsan_shadow_fill((uintptr_t)addr, c, size);
550}
551
552void
553kmsan_mark_bio(const struct bio *bp, uint8_t c)
554{
555 kmsan_mark(bp->bio_data, bp->bio_length, c);
556}
557
558static void
559kmsan_mark_ccb(const union ccb *ccb, uint8_t c)
560{
561 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_IN)
562 return;
563 if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
564 return;
565
566 switch (ccb->ccb_h.func_code) {
567 case XPT_SCSI_IO: {
568 const struct ccb_scsiio *scsiio;
569
570 scsiio = &ccb->ctio;
571 kmsan_mark(scsiio->data_ptr, scsiio->dxfer_len, c);
572 break;
573 }
574 case XPT_ATA_IO: {
575 const struct ccb_ataio *ataio;
576
577 ataio = &ccb->ataio;
578 kmsan_mark(ataio->data_ptr, ataio->dxfer_len, c);
579 break;
580 }
581 case XPT_NVME_IO: {
582 const struct ccb_nvmeio *nvmeio;
583
584 nvmeio = &ccb->nvmeio;
585 kmsan_mark(nvmeio->data_ptr, nvmeio->dxfer_len, c);
586 break;
587 }
588 default:
589 kmsan_panic("%s: unhandled CCB type %d", __func__,
590 ccb->ccb_h.func_code);
591 }
592}
593
594void
595kmsan_mark_mbuf(const struct mbuf *m, uint8_t c)
596{
597 do {
598 if ((m->m_flags & M_EXTPG) == 0)
599 kmsan_mark(m->m_data, m->m_len, c);
600 m = m->m_next;
601 } while (m != NULL);
602}
603
604void
605kmsan_check(const void *p, size_t sz, const char *descr)
606{
607 kmsan_shadow_check((uintptr_t)p, sz, descr);
608}
609
610void
611kmsan_check_bio(const struct bio *bp, const char *descr)
612{
613 kmsan_shadow_check((uintptr_t)bp->bio_data, bp->bio_length, descr);
614}
615
616void
617kmsan_check_ccb(const union ccb *ccb, const char *descr)
618{
619 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT)
620 return;
621 switch (ccb->ccb_h.func_code) {
622 case XPT_SCSI_IO: {
623 const struct ccb_scsiio *scsiio;
624
625 scsiio = &ccb->ctio;
626 kmsan_check(scsiio->data_ptr, scsiio->dxfer_len, descr);
627 break;
628 }
629 case XPT_ATA_IO: {
630 const struct ccb_ataio *ataio;
631
632 ataio = &ccb->ataio;
633 kmsan_check(ataio->data_ptr, ataio->dxfer_len, descr);
634 break;
635 }
636 case XPT_NVME_IO: {
637 const struct ccb_nvmeio *nvmeio;
638
639 nvmeio = &ccb->nvmeio;
640 kmsan_check(nvmeio->data_ptr, nvmeio->dxfer_len, descr);
641 break;
642 }
643 default:
644 kmsan_panic("%s: unhandled CCB type %d", __func__,
645 ccb->ccb_h.func_code);
646 }
647}
648
649void
650kmsan_check_mbuf(const struct mbuf *m, const char *descr)
651{
652 do {
653 kmsan_shadow_check((uintptr_t)mtod(m, void *), m->m_len, descr);
654 } while ((m = m->m_next) != NULL);
655}
656
657void
659{
660 int disabled;
661
662 disabled = 0;
663 TUNABLE_INT_FETCH("debug.kmsan.disabled", &disabled);
664 if (disabled)
665 return;
666
667 /* Initialize the TLS for curthread. */
668 msan_thread0.ctx = 0;
669 thread0.td_kmsan = &msan_thread0;
670
671 /* Now officially enabled. */
672 kmsan_enabled = true;
673}
674
675/* -------------------------------------------------------------------------- */
676
679
682{
683 return (kmsan_meta_get(addr, size, false));
684}
685
688{
689 return (kmsan_meta_get(addr, size, true));
690}
691
692#define MSAN_META_FUNC(size) \
693 msan_meta_t __msan_metadata_ptr_for_load_##size(void *); \
694 msan_meta_t __msan_metadata_ptr_for_load_##size(void *addr) \
695 { \
696 return (kmsan_meta_get(addr, size, false)); \
697 } \
698 msan_meta_t __msan_metadata_ptr_for_store_##size(void *); \
699 msan_meta_t __msan_metadata_ptr_for_store_##size(void *addr) \
700 { \
701 return (kmsan_meta_get(addr, size, true)); \
702 }
703
708
709void __msan_instrument_asm_store(const void *, size_t);
710msan_orig_t __msan_chain_origin(msan_orig_t);
711void __msan_poison(const void *, size_t);
712void __msan_unpoison(const void *, size_t);
713void __msan_poison_alloca(const void *, uint64_t, const char *);
714void __msan_unpoison_alloca(const void *, uint64_t);
715void __msan_warning(msan_orig_t);
717
718void
719__msan_instrument_asm_store(const void *addr, size_t size)
720{
721 kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
722}
723
724msan_orig_t
725__msan_chain_origin(msan_orig_t origin)
726{
727 return (origin);
728}
729
730void
731__msan_poison(const void *addr, size_t size)
732{
733 kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_UNINIT, size);
734}
735
736void
737__msan_unpoison(const void *addr, size_t size)
738{
739 kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
740}
741
742void
743__msan_poison_alloca(const void *addr, uint64_t size, const char *descr)
744{
745 msan_orig_t orig;
746
747 orig = kmsan_md_orig_encode(KMSAN_TYPE_STACK, (uintptr_t)descr);
748 kmsan_origin_fill(addr, orig, size);
749 kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_UNINIT, size);
750}
751
752void
753__msan_unpoison_alloca(const void *addr, uint64_t size)
754{
755 kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
756}
757
758void
759__msan_warning(msan_orig_t origin)
760{
761 if (__predict_false(!kmsan_enabled))
762 return;
763 kmsan_report_inline(origin, KMSAN_RET_ADDR);
764}
765
768{
769 msan_td_t *mtd;
770
771 /*
772 * When APs are started, they execute some C code before curthread is
773 * set. We have to handle that here.
774 */
775 if (__predict_false(!kmsan_enabled || curthread == NULL))
776 return (&dummy_tls);
777 mtd = curthread->td_kmsan;
778 return (&mtd->tls[mtd->ctx]);
779}
780
781/* -------------------------------------------------------------------------- */
782
783/*
784 * Function hooks. Mostly ASM functions which need KMSAN wrappers to handle
785 * initialized areas properly.
786 */
787
788void *
789kmsan_memcpy(void *dst, const void *src, size_t len)
790{
791 /* No kmsan_check_arg, because inlined. */
792 kmsan_init_ret(sizeof(void *));
793 if (__predict_true(len != 0)) {
794 kmsan_meta_copy(dst, src, len);
795 }
796 return (__builtin_memcpy(dst, src, len));
797}
798
799int
800kmsan_memcmp(const void *b1, const void *b2, size_t len)
801{
802 const uint8_t *_b1 = b1, *_b2 = b2;
803 size_t i;
804
805 kmsan_check_arg(sizeof(b1) + sizeof(b2) + sizeof(len),
806 "memcmp():args");
807 kmsan_init_ret(sizeof(int));
808
809 for (i = 0; i < len; i++) {
810 if (*_b1 != *_b2) {
811 kmsan_shadow_check((uintptr_t)b1, i + 1,
812 "memcmp():arg1");
813 kmsan_shadow_check((uintptr_t)b2, i + 1,
814 "memcmp():arg2");
815 return (*_b1 - *_b2);
816 }
817 _b1++, _b2++;
818 }
819
820 return (0);
821}
822
823void *
824kmsan_memset(void *dst, int c, size_t len)
825{
826 /* No kmsan_check_arg, because inlined. */
827 kmsan_shadow_fill((uintptr_t)dst, KMSAN_STATE_INITED, len);
828 kmsan_init_ret(sizeof(void *));
829 return (__builtin_memset(dst, c, len));
830}
831
832void *
833kmsan_memmove(void *dst, const void *src, size_t len)
834{
835 /* No kmsan_check_arg, because inlined. */
836 if (__predict_true(len != 0)) {
837 kmsan_meta_copy(dst, src, len);
838 }
839 kmsan_init_ret(sizeof(void *));
840 return (__builtin_memmove(dst, src, len));
841}
842
846
847char *
848kmsan_strcpy(char *dst, const char *src)
849{
850 const char *_src = src;
851 char *_dst = dst;
852 size_t len = 0;
853
854 kmsan_check_arg(sizeof(dst) + sizeof(src), "strcpy():args");
855
856 while (1) {
857 len++;
858 *dst = *src;
859 if (*src == '\0')
860 break;
861 src++, dst++;
862 }
863
864 kmsan_shadow_check((uintptr_t)_src, len, "strcpy():arg2");
865 kmsan_shadow_fill((uintptr_t)_dst, KMSAN_STATE_INITED, len);
866 kmsan_init_ret(sizeof(char *));
867 return (_dst);
868}
869
870int
871kmsan_strcmp(const char *s1, const char *s2)
872{
873 const char *_s1 = s1, *_s2 = s2;
874 size_t len = 0;
875
876 kmsan_check_arg(sizeof(s1) + sizeof(s2), "strcmp():args");
877 kmsan_init_ret(sizeof(int));
878
879 while (1) {
880 len++;
881 if (*s1 != *s2)
882 break;
883 if (*s1 == '\0') {
884 kmsan_shadow_check((uintptr_t)_s1, len, "strcmp():arg1");
885 kmsan_shadow_check((uintptr_t)_s2, len, "strcmp():arg2");
886 return (0);
887 }
888 s1++, s2++;
889 }
890
891 kmsan_shadow_check((uintptr_t)_s1, len, "strcmp():arg1");
892 kmsan_shadow_check((uintptr_t)_s2, len, "strcmp():arg2");
893
894 return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
895}
896
897size_t
898kmsan_strlen(const char *str)
899{
900 const char *s;
901
902 kmsan_check_arg(sizeof(str), "strlen():args");
903
904 s = str;
905 while (1) {
906 if (*s == '\0')
907 break;
908 s++;
909 }
910
911 kmsan_shadow_check((uintptr_t)str, (size_t)(s - str) + 1, "strlen():arg1");
912 kmsan_init_ret(sizeof(size_t));
913 return (s - str);
914}
915
916int kmsan_copyin(const void *, void *, size_t);
917int kmsan_copyout(const void *, void *, size_t);
918int kmsan_copyinstr(const void *, void *, size_t, size_t *);
919
920int
921kmsan_copyin(const void *uaddr, void *kaddr, size_t len)
922{
923 int ret;
924
925 kmsan_check_arg(sizeof(uaddr) + sizeof(kaddr) + sizeof(len),
926 "copyin():args");
927 ret = copyin(uaddr, kaddr, len);
928 if (ret == 0)
929 kmsan_shadow_fill((uintptr_t)kaddr, KMSAN_STATE_INITED, len);
930 kmsan_init_ret(sizeof(int));
931 return (ret);
932}
933
934int
935kmsan_copyout(const void *kaddr, void *uaddr, size_t len)
936{
937 kmsan_check_arg(sizeof(kaddr) + sizeof(uaddr) + sizeof(len),
938 "copyout():args");
939 kmsan_shadow_check((uintptr_t)kaddr, len, "copyout():arg1");
940 kmsan_init_ret(sizeof(int));
941 return (copyout(kaddr, uaddr, len));
942}
943
944int
945kmsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
946{
947 size_t _done;
948 int ret;
949
950 kmsan_check_arg(sizeof(uaddr) + sizeof(kaddr) +
951 sizeof(len) + sizeof(done), "copyinstr():args");
952 ret = copyinstr(uaddr, kaddr, len, &_done);
953 if (ret == 0)
954 kmsan_shadow_fill((uintptr_t)kaddr, KMSAN_STATE_INITED, _done);
955 if (done != NULL) {
956 *done = _done;
957 kmsan_shadow_fill((uintptr_t)done, KMSAN_STATE_INITED, sizeof(size_t));
958 }
959 kmsan_init_ret(sizeof(int));
960 return (ret);
961}
962
963/* -------------------------------------------------------------------------- */
964
965int
966kmsan_fubyte(volatile const void *base)
967{
968 int ret;
969
970 kmsan_check_arg(sizeof(base), "fubyte(): args");
971 ret = fubyte(base);
972 kmsan_init_ret(sizeof(int));
973 return (ret);
974}
975
976int
977kmsan_fuword16(volatile const void *base)
978{
979 int ret;
980
981 kmsan_check_arg(sizeof(base), "fuword16(): args");
982 ret = fuword16(base);
983 kmsan_init_ret(sizeof(int));
984 return (ret);
985}
986
987int
988kmsan_fueword(volatile const void *base, long *val)
989{
990 int ret;
991
992 kmsan_check_arg(sizeof(base) + sizeof(val), "fueword(): args");
993 ret = fueword(base, val);
994 if (ret == 0)
995 kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
996 sizeof(*val));
997 kmsan_init_ret(sizeof(int));
998 return (ret);
999}
1000
1001int
1002kmsan_fueword32(volatile const void *base, int32_t *val)
1003{
1004 int ret;
1005
1006 kmsan_check_arg(sizeof(base) + sizeof(val), "fueword32(): args");
1007 ret = fueword32(base, val);
1008 if (ret == 0)
1009 kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
1010 sizeof(*val));
1011 kmsan_init_ret(sizeof(int));
1012 return (ret);
1013}
1014
1015int
1016kmsan_fueword64(volatile const void *base, int64_t *val)
1017{
1018 int ret;
1019
1020 kmsan_check_arg(sizeof(base) + sizeof(val), "fueword64(): args");
1021 ret = fueword64(base, val);
1022 if (ret == 0)
1023 kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
1024 sizeof(*val));
1025 kmsan_init_ret(sizeof(int));
1026 return (ret);
1027}
1028
1029int
1030kmsan_subyte(volatile void *base, int byte)
1031{
1032 int ret;
1033
1034 kmsan_check_arg(sizeof(base) + sizeof(byte), "subyte():args");
1035 ret = subyte(base, byte);
1036 kmsan_init_ret(sizeof(int));
1037 return (ret);
1038}
1039
1040int
1041kmsan_suword(volatile void *base, long word)
1042{
1043 int ret;
1044
1045 kmsan_check_arg(sizeof(base) + sizeof(word), "suword():args");
1046 ret = suword(base, word);
1047 kmsan_init_ret(sizeof(int));
1048 return (ret);
1049}
1050
1051int
1052kmsan_suword16(volatile void *base, int word)
1053{
1054 int ret;
1055
1056 kmsan_check_arg(sizeof(base) + sizeof(word), "suword16():args");
1057 ret = suword16(base, word);
1058 kmsan_init_ret(sizeof(int));
1059 return (ret);
1060}
1061
1062int
1063kmsan_suword32(volatile void *base, int32_t word)
1064{
1065 int ret;
1066
1067 kmsan_check_arg(sizeof(base) + sizeof(word), "suword32():args");
1068 ret = suword32(base, word);
1069 kmsan_init_ret(sizeof(int));
1070 return (ret);
1071}
1072
1073int
1074kmsan_suword64(volatile void *base, int64_t word)
1075{
1076 int ret;
1077
1078 kmsan_check_arg(sizeof(base) + sizeof(word), "suword64():args");
1079 ret = suword64(base, word);
1080 kmsan_init_ret(sizeof(int));
1081 return (ret);
1082}
1083
1084int
1085kmsan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
1086 uint32_t newval)
1087{
1088 int ret;
1089
1090 kmsan_check_arg(sizeof(base) + sizeof(oldval) + sizeof(oldvalp) +
1091 sizeof(newval), "casueword32(): args");
1092 ret = casueword32(base, oldval, oldvalp, newval);
1093 kmsan_shadow_fill((uintptr_t)oldvalp, KMSAN_STATE_INITED,
1094 sizeof(*oldvalp));
1095 kmsan_init_ret(sizeof(int));
1096 return (ret);
1097}
1098
1099int
1100kmsan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp,
1101 u_long newval)
1102{
1103 int ret;
1104
1105 kmsan_check_arg(sizeof(base) + sizeof(oldval) + sizeof(oldvalp) +
1106 sizeof(newval), "casueword32(): args");
1107 ret = casueword(base, oldval, oldvalp, newval);
1108 kmsan_shadow_fill((uintptr_t)oldvalp, KMSAN_STATE_INITED,
1109 sizeof(*oldvalp));
1110 kmsan_init_ret(sizeof(int));
1111 return (ret);
1112}
1113
1114/* -------------------------------------------------------------------------- */
1115
1116#include <machine/atomic.h>
1117#include <sys/atomic_san.h>
1118
1119#define _MSAN_ATOMIC_FUNC_ADD(name, type) \
1120 void kmsan_atomic_add_##name(volatile type *ptr, type val) \
1121 { \
1122 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1123 "atomic_add_" #name "():args"); \
1124 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1125 "atomic_add_" #name "():ptr"); \
1126 atomic_add_##name(ptr, val); \
1127 }
1128
1129#define MSAN_ATOMIC_FUNC_ADD(name, type) \
1130 _MSAN_ATOMIC_FUNC_ADD(name, type) \
1131 _MSAN_ATOMIC_FUNC_ADD(acq_##name, type) \
1132 _MSAN_ATOMIC_FUNC_ADD(rel_##name, type)
1133
1134#define _MSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
1135 void kmsan_atomic_subtract_##name(volatile type *ptr, type val) \
1136 { \
1137 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1138 "atomic_subtract_" #name "():args"); \
1139 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1140 "atomic_subtract_" #name "():ptr"); \
1141 atomic_subtract_##name(ptr, val); \
1142 }
1143
1144#define MSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
1145 _MSAN_ATOMIC_FUNC_SUBTRACT(name, type) \
1146 _MSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type) \
1147 _MSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
1148
1149#define _MSAN_ATOMIC_FUNC_SET(name, type) \
1150 void kmsan_atomic_set_##name(volatile type *ptr, type val) \
1151 { \
1152 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1153 "atomic_set_" #name "():args"); \
1154 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1155 "atomic_set_" #name "():ptr"); \
1156 atomic_set_##name(ptr, val); \
1157 }
1158
1159#define MSAN_ATOMIC_FUNC_SET(name, type) \
1160 _MSAN_ATOMIC_FUNC_SET(name, type) \
1161 _MSAN_ATOMIC_FUNC_SET(acq_##name, type) \
1162 _MSAN_ATOMIC_FUNC_SET(rel_##name, type)
1163
1164#define _MSAN_ATOMIC_FUNC_CLEAR(name, type) \
1165 void kmsan_atomic_clear_##name(volatile type *ptr, type val) \
1166 { \
1167 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1168 "atomic_clear_" #name "():args"); \
1169 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1170 "atomic_clear_" #name "():ptr"); \
1171 atomic_clear_##name(ptr, val); \
1172 }
1173
1174#define MSAN_ATOMIC_FUNC_CLEAR(name, type) \
1175 _MSAN_ATOMIC_FUNC_CLEAR(name, type) \
1176 _MSAN_ATOMIC_FUNC_CLEAR(acq_##name, type) \
1177 _MSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
1178
1179#define MSAN_ATOMIC_FUNC_FETCHADD(name, type) \
1180 type kmsan_atomic_fetchadd_##name(volatile type *ptr, type val) \
1181 { \
1182 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1183 "atomic_fetchadd_" #name "():args"); \
1184 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1185 "atomic_fetchadd_" #name "():ptr"); \
1186 kmsan_init_ret(sizeof(type)); \
1187 return (atomic_fetchadd_##name(ptr, val)); \
1188 }
1189
1190#define MSAN_ATOMIC_FUNC_READANDCLEAR(name, type) \
1191 type kmsan_atomic_readandclear_##name(volatile type *ptr) \
1192 { \
1193 kmsan_check_arg(sizeof(ptr), \
1194 "atomic_readandclear_" #name "():args"); \
1195 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1196 "atomic_readandclear_" #name "():ptr"); \
1197 kmsan_init_ret(sizeof(type)); \
1198 return (atomic_readandclear_##name(ptr)); \
1199 }
1200
1201#define MSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type) \
1202 int kmsan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
1203 { \
1204 kmsan_check_arg(sizeof(ptr) + sizeof(v), \
1205 "atomic_testandclear_" #name "():args"); \
1206 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1207 "atomic_testandclear_" #name "():ptr"); \
1208 kmsan_init_ret(sizeof(int)); \
1209 return (atomic_testandclear_##name(ptr, v)); \
1210 }
1211
1212#define MSAN_ATOMIC_FUNC_TESTANDSET(name, type) \
1213 int kmsan_atomic_testandset_##name(volatile type *ptr, u_int v) \
1214 { \
1215 kmsan_check_arg(sizeof(ptr) + sizeof(v), \
1216 "atomic_testandset_" #name "():args"); \
1217 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1218 "atomic_testandset_" #name "():ptr"); \
1219 kmsan_init_ret(sizeof(int)); \
1220 return (atomic_testandset_##name(ptr, v)); \
1221 }
1222
1223#define MSAN_ATOMIC_FUNC_SWAP(name, type) \
1224 type kmsan_atomic_swap_##name(volatile type *ptr, type val) \
1225 { \
1226 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1227 "atomic_swap_" #name "():args"); \
1228 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1229 "atomic_swap_" #name "():ptr"); \
1230 kmsan_init_ret(sizeof(type)); \
1231 return (atomic_swap_##name(ptr, val)); \
1232 }
1233
1234#define _MSAN_ATOMIC_FUNC_CMPSET(name, type) \
1235 int kmsan_atomic_cmpset_##name(volatile type *ptr, type oval, \
1236 type nval) \
1237 { \
1238 kmsan_check_arg(sizeof(ptr) + sizeof(oval) + \
1239 sizeof(nval), "atomic_cmpset_" #name "():args"); \
1240 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1241 "atomic_cmpset_" #name "():ptr"); \
1242 kmsan_init_ret(sizeof(int)); \
1243 return (atomic_cmpset_##name(ptr, oval, nval)); \
1244 }
1245
1246#define MSAN_ATOMIC_FUNC_CMPSET(name, type) \
1247 _MSAN_ATOMIC_FUNC_CMPSET(name, type) \
1248 _MSAN_ATOMIC_FUNC_CMPSET(acq_##name, type) \
1249 _MSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
1250
1251#define _MSAN_ATOMIC_FUNC_FCMPSET(name, type) \
1252 int kmsan_atomic_fcmpset_##name(volatile type *ptr, type *oval, \
1253 type nval) \
1254 { \
1255 kmsan_check_arg(sizeof(ptr) + sizeof(oval) + \
1256 sizeof(nval), "atomic_fcmpset_" #name "():args"); \
1257 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1258 "atomic_fcmpset_" #name "():ptr"); \
1259 kmsan_init_ret(sizeof(int)); \
1260 return (atomic_fcmpset_##name(ptr, oval, nval)); \
1261 }
1262
1263#define MSAN_ATOMIC_FUNC_FCMPSET(name, type) \
1264 _MSAN_ATOMIC_FUNC_FCMPSET(name, type) \
1265 _MSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type) \
1266 _MSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
1267
1268#define MSAN_ATOMIC_FUNC_THREAD_FENCE(name) \
1269 void kmsan_atomic_thread_fence_##name(void) \
1270 { \
1271 atomic_thread_fence_##name(); \
1272 }
1273
1274#define _MSAN_ATOMIC_FUNC_LOAD(name, type) \
1275 type kmsan_atomic_load_##name(volatile type *ptr) \
1276 { \
1277 kmsan_check_arg(sizeof(ptr), \
1278 "atomic_load_" #name "():args"); \
1279 kmsan_shadow_check((uintptr_t)ptr, sizeof(type), \
1280 "atomic_load_" #name "():ptr"); \
1281 kmsan_init_ret(sizeof(type)); \
1282 return (atomic_load_##name(ptr)); \
1283 }
1284
1285#define MSAN_ATOMIC_FUNC_LOAD(name, type) \
1286 _MSAN_ATOMIC_FUNC_LOAD(name, type) \
1287 _MSAN_ATOMIC_FUNC_LOAD(acq_##name, type)
1288
1289#define _MSAN_ATOMIC_FUNC_STORE(name, type) \
1290 void kmsan_atomic_store_##name(volatile type *ptr, type val) \
1291 { \
1292 kmsan_check_arg(sizeof(ptr) + sizeof(val), \
1293 "atomic_store_" #name "():args"); \
1294 kmsan_shadow_fill((uintptr_t)ptr, KMSAN_STATE_INITED, \
1295 sizeof(type)); \
1296 atomic_store_##name(ptr, val); \
1297 }
1298
1299#define MSAN_ATOMIC_FUNC_STORE(name, type) \
1300 _MSAN_ATOMIC_FUNC_STORE(name, type) \
1301 _MSAN_ATOMIC_FUNC_STORE(rel_##name, type)
1302
1309MSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
1310
1318
1325MSAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
1326
1334
1339
1345
1350
1355
1361
1369
1377
1387
1397
1402
1403void
1405{
1406 atomic_interrupt_fence();
1407}
1408
1409/* -------------------------------------------------------------------------- */
1410
1411#include <sys/bus.h>
1412#include <machine/bus.h>
1413#include <sys/bus_san.h>
1414
1415int
1416kmsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
1417 int flags, bus_space_handle_t *handlep)
1418{
1419 return (bus_space_map(tag, hnd, size, flags, handlep));
1420}
1421
1422void
1423kmsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
1424 bus_size_t size)
1425{
1426 bus_space_unmap(tag, hnd, size);
1427}
1428
1429int
1430kmsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
1431 bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
1432{
1433 return (bus_space_subregion(tag, hnd, offset, size, handlep));
1434}
1435
1436void
1437kmsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
1438 bus_size_t size)
1439{
1440 bus_space_free(tag, hnd, size);
1441}
1442
1443void
1444kmsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
1445 bus_size_t offset, bus_size_t size, int flags)
1446{
1447 bus_space_barrier(tag, hnd, offset, size, flags);
1448}
1449
1450/* XXXMJ x86-specific */
1451#define MSAN_BUS_READ_FUNC(func, width, type) \
1452 type kmsan_bus_space_read##func##_##width(bus_space_tag_t tag, \
1453 bus_space_handle_t hnd, bus_size_t offset) \
1454 { \
1455 type ret; \
1456 if ((tag) != X86_BUS_SPACE_IO) \
1457 kmsan_shadow_fill((uintptr_t)(hnd + offset), \
1458 KMSAN_STATE_INITED, (width)); \
1459 ret = bus_space_read##func##_##width(tag, hnd, offset); \
1460 kmsan_init_ret(sizeof(type)); \
1461 return (ret); \
1462 } \
1463
1464#define MSAN_BUS_READ_PTR_FUNC(func, width, type) \
1465 void kmsan_bus_space_read_##func##_##width(bus_space_tag_t tag, \
1466 bus_space_handle_t hnd, bus_size_t size, type *buf, \
1467 bus_size_t count) \
1468 { \
1469 kmsan_shadow_fill((uintptr_t)buf, KMSAN_STATE_INITED, \
1470 (width) * count); \
1471 bus_space_read_##func##_##width(tag, hnd, size, buf, \
1472 count); \
1473 }
1474
1475MSAN_BUS_READ_FUNC(, 1, uint8_t)
1476MSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
1477MSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
1478MSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
1479MSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
1480MSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
1481
1482MSAN_BUS_READ_FUNC(, 2, uint16_t)
1483MSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
1484MSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
1485MSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
1486MSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
1487MSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
1488
1489MSAN_BUS_READ_FUNC(, 4, uint32_t)
1490MSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
1491MSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
1492MSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
1493MSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
1494MSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
1495
1496MSAN_BUS_READ_FUNC(, 8, uint64_t)
1497
1498#define MSAN_BUS_WRITE_FUNC(func, width, type) \
1499 void kmsan_bus_space_write##func##_##width(bus_space_tag_t tag, \
1500 bus_space_handle_t hnd, bus_size_t offset, type value) \
1501 { \
1502 bus_space_write##func##_##width(tag, hnd, offset, value);\
1503 } \
1504
1505#define MSAN_BUS_WRITE_PTR_FUNC(func, width, type) \
1506 void kmsan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
1507 bus_space_handle_t hnd, bus_size_t size, const type *buf, \
1508 bus_size_t count) \
1509 { \
1510 kmsan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
1511 "bus_space_write()"); \
1512 bus_space_write_##func##_##width(tag, hnd, size, buf, \
1513 count); \
1514 }
1515
1516MSAN_BUS_WRITE_FUNC(, 1, uint8_t)
1517MSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
1518MSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
1519MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
1521MSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
1522
1523MSAN_BUS_WRITE_FUNC(, 2, uint16_t)
1524MSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
1525MSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
1526MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
1527MSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
1528MSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
1529
1530MSAN_BUS_WRITE_FUNC(, 4, uint32_t)
1531MSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
1532MSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
1533MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
1534MSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
1535MSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
1536
1537MSAN_BUS_WRITE_FUNC(, 8, uint64_t)
1538
1539#define MSAN_BUS_SET_FUNC(func, width, type) \
1540 void kmsan_bus_space_set_##func##_##width(bus_space_tag_t tag, \
1541 bus_space_handle_t hnd, bus_size_t offset, type value, \
1542 bus_size_t count) \
1543 { \
1544 bus_space_set_##func##_##width(tag, hnd, offset, value, \
1545 count); \
1546 }
1547
1548MSAN_BUS_SET_FUNC(multi, 1, uint8_t)
1549MSAN_BUS_SET_FUNC(region, 1, uint8_t)
1550MSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
1551MSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
1552
1553MSAN_BUS_SET_FUNC(multi, 2, uint16_t)
1554MSAN_BUS_SET_FUNC(region, 2, uint16_t)
1555MSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
1556MSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
1557
1558MSAN_BUS_SET_FUNC(multi, 4, uint32_t)
1559MSAN_BUS_SET_FUNC(region, 4, uint32_t)
1560MSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
1561MSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
1562
1563/* -------------------------------------------------------------------------- */
1564
1565void
1566kmsan_bus_dmamap_sync(struct memdesc *desc, bus_dmasync_op_t op)
1567{
1568 /*
1569 * Some drivers, e.g., nvme, use the same code path for loading device
1570 * read and write requests, and will thus specify both flags. In this
1571 * case we should not do any checking since it will generally lead to
1572 * false positives.
1573 */
1574 if ((op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) ==
1575 BUS_DMASYNC_PREWRITE) {
1576 switch (desc->md_type) {
1577 case MEMDESC_VADDR:
1578 kmsan_check(desc->u.md_vaddr, desc->md_opaque,
1579 "dmasync");
1580 break;
1581 case MEMDESC_BIO:
1582 kmsan_check_bio(desc->u.md_bio, "dmasync");
1583 break;
1584 case MEMDESC_MBUF:
1585 kmsan_check_mbuf(desc->u.md_mbuf, "dmasync");
1586 break;
1587 case MEMDESC_CCB:
1588 kmsan_check_ccb(desc->u.md_ccb, "dmasync");
1589 break;
1590 case 0:
1591 break;
1592 default:
1593 kmsan_panic("%s: unhandled memdesc type %d", __func__,
1594 desc->md_type);
1595 }
1596 }
1597 if ((op & BUS_DMASYNC_POSTREAD) != 0) {
1598 switch (desc->md_type) {
1599 case MEMDESC_VADDR:
1600 kmsan_mark(desc->u.md_vaddr, desc->md_opaque,
1601 KMSAN_STATE_INITED);
1602 break;
1603 case MEMDESC_BIO:
1604 kmsan_mark_bio(desc->u.md_bio, KMSAN_STATE_INITED);
1605 break;
1606 case MEMDESC_MBUF:
1607 kmsan_mark_mbuf(desc->u.md_mbuf, KMSAN_STATE_INITED);
1608 break;
1609 case MEMDESC_CCB:
1610 kmsan_mark_ccb(desc->u.md_ccb, KMSAN_STATE_INITED);
1611 break;
1612 case 0:
1613 break;
1614 default:
1615 kmsan_panic("%s: unhandled memdesc type %d", __func__,
1616 desc->md_type);
1617 }
1618 }
1619}
device_property_type_t type
Definition: bus_if.m:941
int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, long *offset)
Definition: kern_linker.c:1031
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
Definition: kern_malloc.c:632
void free(void *addr, struct malloc_type *mtp)
Definition: kern_malloc.c:907
const char * panicstr
uint64_t * addr
Definition: msi_if.m:89
struct intr_irqsrc ** src
Definition: msi_if.m:76
size_t ctx
Definition: subr_msan.c:101
msan_tls_t tls[MSAN_NCONTEXT]
Definition: subr_msan.c:102
uint8_t * shad
Definition: subr_msan.c:79
msan_orig_t * orig
Definition: subr_msan.c:80
msan_orig_t retval_origin
Definition: subr_msan.c:92
uint8_t param_shadow[MSAN_PARAM_SIZE]
Definition: subr_msan.c:86
uint64_t va_arg_overflow_size
Definition: subr_msan.c:90
uint8_t retval_shadow[MSAN_RETVAL_SIZE]
Definition: subr_msan.c:87
u_char __read_frequently kdb_active
Definition: subr_kdb.c:56
void __msan_poison_alloca(const void *, uint64_t, const char *)
Definition: subr_msan.c:743
void * kmsan_memmove(void *dst, const void *src, size_t len)
Definition: subr_msan.c:833
void kmsan_thread_free(struct thread *td)
Definition: subr_msan.c:464
FEATURE(kmsan, "Kernel memory sanitizer")
void kmsan_thread_alloc(struct thread *td)
Definition: subr_msan.c:439
static void kmsan_report_inline(msan_orig_t orig, unsigned long pc)
Definition: subr_msan.c:228
void __msan_instrument_asm_store(const void *, size_t)
Definition: subr_msan.c:719
int kmsan_fueword32(volatile const void *base, int32_t *val)
Definition: subr_msan.c:1002
void kmsan_check_bio(const struct bio *bp, const char *descr)
Definition: subr_msan.c:611
#define MSAN_PARAM_SIZE
Definition: subr_msan.c:83
#define MSAN_ATOMIC_FUNC_THREAD_FENCE(name)
Definition: subr_msan.c:1268
void kmsan_init_ret(size_t)
Definition: subr_msan.c:402
void kmsan_orig(const void *addr, size_t size, int type, uintptr_t pc)
Definition: subr_msan.c:538
char * kmsan_strcpy(char *dst, const char *src)
Definition: subr_msan.c:848
int kmsan_fueword64(volatile const void *base, int64_t *val)
Definition: subr_msan.c:1016
static bool panic_on_violation
Definition: subr_msan.c:144
#define MSAN_ATOMIC_FUNC_FETCHADD(name, type)
Definition: subr_msan.c:1179
void kmsan_check(const void *p, size_t sz, const char *descr)
Definition: subr_msan.c:605
#define MSAN_BUS_READ_PTR_FUNC(func, width, type)
Definition: subr_msan.c:1464
#define MSAN_ATOMIC_FUNC_LOAD(name, type)
Definition: subr_msan.c:1285
void kmsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_msan.c:1423
#define MSAN_BUS_WRITE_PTR_FUNC(func, width, type)
Definition: subr_msan.c:1505
void * kmsan_memcpy(void *dst, const void *src, size_t len)
Definition: subr_msan.c:789
#define MSAN_RETVAL_SIZE
Definition: subr_msan.c:84
static void kmsan_report_hook(const void *addr, size_t size, size_t off, const char *hook)
Definition: subr_msan.c:171
#define MSAN_NCONTEXT
Definition: subr_msan.c:97
size_t kmsan_strlen(const char *str)
Definition: subr_msan.c:898
static void kmsan_shadow_fill(uintptr_t addr, uint8_t c, size_t size)
Definition: subr_msan.c:321
void kmsan_intr_leave(void)
Definition: subr_msan.c:497
#define MSAN_ATOMIC_FUNC_TESTANDSET(name, type)
Definition: subr_msan.c:1212
static void kmsan_shadow_check(uintptr_t addr, size_t size, const char *hook)
Definition: subr_msan.c:367
static SYSCTL_NODE(_debug, OID_AUTO, kmsan, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "KMSAN options")
#define MSAN_ATOMIC_FUNC_STORE(name, type)
Definition: subr_msan.c:1299
#define MSAN_BUS_READ_FUNC(func, width, type)
Definition: subr_msan.c:1451
int kmsan_memcmp(const void *b1, const void *b2, size_t len)
Definition: subr_msan.c:800
msan_tls_t * __msan_get_context_state(void)
Definition: subr_msan.c:767
static msan_meta_t kmsan_meta_get(const void *addr, size_t size, const bool write)
Definition: subr_msan.c:279
#define MSAN_ATOMIC_FUNC_ADD(name, type)
Definition: subr_msan.c:1129
#define MSAN_BUS_SET_FUNC(func, width, type)
Definition: subr_msan.c:1539
int kmsan_suword(volatile void *base, long word)
Definition: subr_msan.c:1041
int kmsan_suword32(volatile void *base, int32_t word)
Definition: subr_msan.c:1063
void kmsan_shadow_map(vm_offset_t addr, size_t size)
Definition: subr_msan.c:513
int kmsan_copyin(const void *, void *, size_t)
Definition: subr_msan.c:921
int kmsan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp, u_long newval)
Definition: subr_msan.c:1100
msan_meta_t __msan_metadata_ptr_for_store_n(void *, size_t)
Definition: subr_msan.c:687
int kmsan_suword64(volatile void *base, int64_t word)
Definition: subr_msan.c:1074
static void kmsan_mark_ccb(const union ccb *ccb, uint8_t c)
Definition: subr_msan.c:559
struct kmsan_td msan_td_t
#define REPORT(f,...)
Definition: subr_msan.c:127
#define MSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)
Definition: subr_msan.c:1201
static bool kmsan_reporting
Definition: subr_msan.c:117
#define MSAN_ATOMIC_FUNC_CMPSET(name, type)
Definition: subr_msan.c:1246
static void kmsan_check_arg(size_t size, const char *hook)
Definition: subr_msan.c:417
#define MSAN_ATOMIC_FUNC_READANDCLEAR(name, type)
Definition: subr_msan.c:1190
int kmsan_copyinstr(const void *, void *, size_t, size_t *)
Definition: subr_msan.c:945
void kmsan_atomic_interrupt_fence(void)
Definition: subr_msan.c:1404
int kmsan_fueword(volatile const void *base, long *val)
Definition: subr_msan.c:988
#define MSAN_BUS_WRITE_FUNC(func, width, type)
Definition: subr_msan.c:1498
msan_meta_t __msan_metadata_ptr_for_load_n(void *, size_t)
Definition: subr_msan.c:681
__FBSDID("$FreeBSD$")
int kmsan_subyte(volatile void *base, int byte)
Definition: subr_msan.c:1030
void kmsan_mark_bio(const struct bio *bp, uint8_t c)
Definition: subr_msan.c:553
void kmsan_mark_mbuf(const struct mbuf *m, uint8_t c)
Definition: subr_msan.c:595
void kmsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t size)
Definition: subr_msan.c:1437
SYSCTL_BOOL(_debug_kmsan, OID_AUTO, panic_on_violation, CTLFLAG_RWTUN, &panic_on_violation, 0, "Panic if an invalid access is detected")
#define MSAN_ATOMIC_FUNC_SWAP(name, type)
Definition: subr_msan.c:1223
static msan_td_t msan_thread0
Definition: subr_msan.c:114
void kmsan_bus_dmamap_sync(struct memdesc *desc, bus_dmasync_op_t op)
Definition: subr_msan.c:1566
void kmsan_mark(const void *addr, size_t size, uint8_t c)
Definition: subr_msan.c:547
void __msan_unpoison_alloca(const void *, uint64_t)
Definition: subr_msan.c:753
void kmsan_check_mbuf(const struct mbuf *m, const char *descr)
Definition: subr_msan.c:650
static bool kmsan_enabled __read_mostly
Definition: subr_msan.c:115
int kmsan_fuword16(volatile const void *base)
Definition: subr_msan.c:977
#define MSAN_ATOMIC_FUNC_CLEAR(name, type)
Definition: subr_msan.c:1174
int kmsan_strcmp(const char *s1, const char *s2)
Definition: subr_msan.c:871
static void kmsan_origin_fill(const void *addr, msan_orig_t o, size_t size)
Definition: subr_msan.c:301
__strong_reference(kmsan_memcpy, __msan_memcpy)
void * kmsan_memset(void *dst, int c, size_t len)
Definition: subr_msan.c:824
void kmsan_init_arg(size_t)
Definition: subr_msan.c:387
int kmsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size, int flags, bus_space_handle_t *handlep)
Definition: subr_msan.c:1416
static uint8_t msan_dummy_shad[PAGE_SIZE] __aligned(PAGE_SIZE)
int kmsan_fubyte(volatile const void *base)
Definition: subr_msan.c:966
int kmsan_suword16(volatile void *base, int word)
Definition: subr_msan.c:1052
void kmsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, int flags)
Definition: subr_msan.c:1444
void __msan_warning(msan_orig_t)
Definition: subr_msan.c:759
int kmsan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp, uint32_t newval)
Definition: subr_msan.c:1085
int kmsan_copyout(const void *, void *, size_t)
Definition: subr_msan.c:935
int kmsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd, bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
Definition: subr_msan.c:1430
void kmsan_intr_enter(void)
Definition: subr_msan.c:483
void __msan_poison(const void *, size_t)
Definition: subr_msan.c:731
msan_orig_t __msan_chain_origin(msan_orig_t)
Definition: subr_msan.c:725
static msan_tls_t dummy_tls
Definition: subr_msan.c:105
#define MSAN_ATOMIC_FUNC_SUBTRACT(name, type)
Definition: subr_msan.c:1144
static const char * kmsan_orig_name(int type)
Definition: subr_msan.c:154
void kmsan_init(void)
Definition: subr_msan.c:658
void kmsan_check_ccb(const union ccb *ccb, const char *descr)
Definition: subr_msan.c:617
#define MSAN_ATOMIC_FUNC_SET(name, type)
Definition: subr_msan.c:1159
static MALLOC_DEFINE(M_KMSAN, "kmsan", "Kernel memory sanitizer")
#define kmsan_panic(f,...)
Definition: subr_msan.c:122
static void kmsan_meta_copy(void *dst, const void *src, size_t size)
Definition: subr_msan.c:335
#define MSAN_ATOMIC_FUNC_FCMPSET(name, type)
Definition: subr_msan.c:1263
#define MSAN_ORIG_MASK
Definition: subr_msan.c:98
#define MSAN_META_FUNC(size)
Definition: subr_msan.c:692
void __msan_unpoison(const void *, size_t)
Definition: subr_msan.c:737
uint16_t flags
Definition: subr_stats.c:2
struct stat * buf