xref: /freebsd/share/man/man9/kmsan.9 (revision 6bfca4dcab07dad45a805879d954876b353c0810)
1.\"-
2.\" Copyright (c) 2021 The FreeBSD Foundation
3.\"
4.\" This documentation was written by Mark Johnston under sponsorship from
5.\" the FreeBSD Foundation.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\"    notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\"    notice, this list of conditions and the following disclaimer in the
14.\"    documentation and/or other materials provided with the distribution.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.Dd October 13, 2023
29.Dt KMSAN 9
30.Os
31.Sh NAME
32.Nm KMSAN
33.Nd Kernel Memory SANitizer
34.Sh SYNOPSIS
35The
36.Pa GENERIC-KMSAN
37kernel configuration can be used to compile a KMSAN-enabled kernel using
38.Pa GENERIC
39as a base configuration.
40Alternately, to compile KMSAN into the kernel, place the following line in your
41kernel configuration file:
42.Bd -ragged -offset indent
43.Cd "options KMSAN"
44.Ed
45.Pp
46.In sys/msan.h
47.Ft void
48.Fn kmsan_mark "const void *addr" "size_t size" "uint8_t code"
49.Ft void
50.Fn kmsan_orig "const void *addr" "size_t size" "int type" "uintptr_t pc"
51.Ft void
52.Fn kmsan_check "const void *addr" "size_t size" "const char *descr"
53.Ft void
54.Fn kmsan_check_bio "const struct bio *" "const char *descr"
55.Ft void
56.Fn kmsan_check_ccb "const union ccb *" "const char *descr"
57.Ft void
58.Fn kmsan_check_mbuf "const struct mbuf *" "const char *descr"
59.Sh DESCRIPTION
60.Nm
61is a subsystem which leverages compiler instrumentation to detect uses of
62uninitialized memory in the kernel.
63Currently it is implemented only on the amd64 platform.
64.Pp
65When
66.Nm
67is compiled into the kernel, the compiler is configured to emit function
68calls preceding memory accesses.
69The functions are implemented by the
70.Nm
71runtime component and use hidden, byte-granular shadow state to determine
72whether the source operand has been initialized.
73When uninitialized memory is used as a source operand in certain operations,
74such as control flow expressions or memory accesses, the runtime reports
75an error.
76Otherwise, the shadow state is propagated to destination operand.
77For example, a
78variable assignment or a
79.Fn memcpy
80call which copies uninitialized memory will cause the destination buffer or
81variable to be marked uninitialized.
82.Pp
83To report an error, the
84.Nm
85runtime will either trigger a kernel panic or print a message to the console,
86depending on the value of the
87.Sy debug.kmsan.panic_on_violation
88sysctl.
89In both cases, a stack trace and information about the origin of the
90uninitialized memory is included.
91.Pp
92In addition to compiler-detected uses of uninitialized memory,
93various kernel I/O
94.Dq exit points ,
95such as
96.Xr copyout 9 ,
97perform validation of the input's shadow state and will raise an error if
98any uninitialized bytes are detected.
99.Pp
100The
101.Nm
102option imposes a significant performance penalty.
103Kernel code typically runs two or three times slower, and each byte mapped in
104the kernel map requires two bytes of shadow state.
105As a result,
106.Nm
107should be used only for kernel testing and development.
108It is not recommended to enable
109.Nm
110in systems with less than 8GB of physical RAM.
111.Pp
112The sanitizer in a KMSAN-configured kernel can be disabled by setting the loader
113tunable
114.Sy debug.kmsan.disable=1 .
115.Sh FUNCTIONS
116The
117.Fn kmsan_mark
118and
119.Fn kmsan_orig
120functions update
121.Nm
122shadow state.
123.Fn kmsan_mark
124marks an address range as valid or invalid according to the value of the
125.Va code
126parameter.
127The valid values for this parameter are
128.Dv KMSAN_STATE_INITED
129and
130.Dv KMSAN_STATE_UNINIT ,
131which mark the range as initialized and uninitialized, respectively.
132For example, when a piece of memory is freed to a kernel allocator, it will
133typically have been marked initialized; before the memory is reused for a new
134allocation, the allocator should mark it as uninitialized.
135As another example, writes to host memory performed by devices, e.g., via DMA,
136are not intercepted by the sanitizer; to avoid false positives, drivers should
137mark device-written memory as initialized.
138For many drivers this is handled internally by the
139.Xr busdma 9
140subsystem.
141.Pp
142The
143.Fn kmsan_orig
144function updates
145.Dq origin
146shadow state.
147In particular, it associates a given uninitialized buffer with a memory type
148and code address.
149This is used by the
150.Nm
151runtime to track the source of uninitialized memory and is only for debugging
152purposes.
153See
154.Sx IMPLEMENTATION NOTES
155for more details.
156.Pp
157The
158.Fn kmsan_check
159function and its sub-typed siblings validate the shadow state of the region(s)
160of kernel memory passed as input parameters.
161If any byte of the input is marked as uninitialized, the runtime will generate
162a report.
163These functions are useful during debugging, as they can be strategically
164inserted into code paths to narrow down the source of uninitialized memory.
165They are also used to perform validation in various kernel I/O paths, helping
166ensure that, for example, packets transmitted over a network do not contain
167uninitialized kernel memory.
168.Fn kmsan_check
169and related functions also take a
170.Fa descr
171parameter which is inserted into any reports raised by the check.
172.Sh IMPLEMENTATION NOTES
173.Ss Shadow Maps
174The
175.Nm
176runtime makes use of two shadows of the kernel map.
177Each address in the kernel map has a linear mapping to addresses in the
178two shadows.
179The first, simply called the shadow map, tracks the state of the corresponding
180kernel memory.
181A non-zero byte in the shadow map indicates that the corresponding byte of
182kernel memory is uninitialized.
183The
184.Nm
185instrumentation automatically propagates shadow state as the contents of kernel
186memory are transformed and copied.
187.Pp
188The second shadow is called the origin map, and exists only to help debug
189reports from the sanitizer.
190To avoid false positives,
191.Nm
192does not raise reports for certain operations on uninitialized memory, such
193as copying or arithmetic.
194Thus, operations on uninitialized state which raise a report may be far removed
195from the source of the bug, complicating debugging.
196The origin map contains information which can help pinpoint the root cause of
197a particular
198.Nm
199report; when generating a report, the runtime uses state from the origin map
200to provide extra details.
201.Pp
202Unlike the shadow map, the origin map is not byte-granular, but consists of 4-byte
203.Dq cells .
204Each cell describes the corresponding four bytes of mapped kernel memory and
205holds a type and compressed code address.
206When kernel memory is allocated for some purpose, its origin is initialized
207either by the compiler instrumentation or by runtime hooks in the allocator.
208The type indicates the specific allocator, e.g.,
209.Xr uma 9 ,
210and the address provides the location in the kernel code where the memory was
211allocated.
212.Ss Assembly Code
213When
214.Nm
215is configured, the compiler will only emit instrumentation for C code.
216Files containing assembly code are left un-instrumented.
217In some cases this is handled by the sanitizer runtime, which defines
218wrappers for subroutines implemented in assembly.
219These wrappers are referred to as interceptors and handle updating
220shadow state to reflect the operations performed by the original
221subroutines.
222In other cases, C code which calls assembly code or is called from
223assembly code may need to use
224.Fn kmsan_mark
225to manually update shadow state.
226This is typically only necessary in machine-dependent code.
227.Pp
228Inline assembly is instrumented by the compiler to update shadow state
229based on the output operands of the code, and thus does not usually
230require any special handling to avoid false positives.
231.Ss Interrupts and Exceptions
232In addition to the shadow maps, the sanitizer requires some thread-local
233storage (TLS) to track initialization and origin state for function
234parameters and return values.
235The sanitizer instrumentation will automatically fetch, update and
236verify this state.
237In particular, this storage block has a layout defined by the sanitizer
238ABI.
239.Pp
240Most kernel code runs in a context where interrupts or exceptions may
241redirect the CPU to begin execution of unrelated code.
242To ensure that thread-local sanitizer state remains consistent, the
243runtime maintains a stack of TLS blocks for each thread.
244When machine-dependent interrupt and exception handlers begin execution,
245they push a new entry onto the stack before calling into any C code, and
246pop the stack before resuming execution of the interrupted code.
247These operations are performed by the
248.Fn kmsan_intr_enter
249and
250.Fn kmsan_intr_leave
251functions in the sanitizer runtime.
252.Sh EXAMPLES
253The following contrived example demonstrates some of the types of bugs
254that are automatically detected by
255.Nm :
256.Bd -literal -offset indent
257int
258f(size_t osz)
259{
260	struct {
261		uint32_t bar;
262		uint16_t baz;
263		/* A 2-byte hole is here. */
264	} foo;
265	char *buf;
266	size_t sz;
267	int error;
268
269	/*
270	 * This will raise a report since "sz" is uninitialized
271	 * here.  If it is initialized, and "osz" was left uninitialized
272	 * by the caller, a report would also be raised.
273	 */
274	if (sz < osz)
275		return (1);
276
277	buf = malloc(32, M_TEMP, M_WAITOK);
278
279	/*
280	 * This will raise a report since "buf" has not been
281	 * initialized and contains whatever data is left over from the
282	 * previous use of that memory.
283	 */
284	for (i = 0; i < 32; i++)
285		if (buf[i] != '\0')
286			foo.bar++;
287	foo.baz = 0;
288
289	/*
290	 * This will raise a report since the pad bytes in "foo" have
291	 * not been initialized, e.g., by memset(), and this call will
292	 * thus copy uninitialized kernel stack memory into userspace.
293	 */
294	copyout(&foo, uaddr, sizeof(foo));
295
296	/*
297	 * This line itself will not raise a report, but may trigger
298	 * a report in the caller depending on how the return value is
299	 * used.
300	 */
301	return (error);
302}
303.Ed
304.Sh SEE ALSO
305.Xr build 7 ,
306.Xr busdma 9 ,
307.Xr copyout 9 ,
308.Xr KASAN 9 ,
309.Xr uma 9
310.Rs
311.%A Evgeniy Stepanov
312.%A Konstantin Serebryany
313.%T MemorySanitizer: fast detector of uninitialized memory use in C++
314.%J 2015 IEEE/ACM International Symposium on Code Generation and Optimization (CGO)
315.%D 2015
316.Re
317.Sh HISTORY
318.Nm
319was ported from
320.Nx
321and first appeared in
322.Fx 14.0 .
323.Sh BUGS
324Accesses to kernel memory outside of the kernel map are ignored by the
325.Nm
326runtime.
327In particular, memory accesses via the direct map are not validated.
328When memory is copied from outside the kernel map into the kernel map,
329that region of the kernel map is marked as initialized.
330When
331.Nm
332is configured, kernel memory allocators are configured to use the kernel map,
333and filesystems are configured to always map data buffers into the kernel map,
334so usage of the direct map is minimized.
335However, some uses of the direct map remain.
336This is a conservative policy which aims to avoid false positives, but it will
337mask bug in some kernel subsystems.
338.Pp
339On amd64, global variables and the physical page array
340.Va vm_page_array
341are not sanitized.
342This is intentional, as it reduces memory usage by avoiding creating
343shadows of large regions of the kernel map.
344However, this can allow bugs to go undetected by
345.Nm .
346.Pp
347Some kernel memory allocators provide type-stable objects, and code which uses
348them frequently depends on object data being preserved across allocations.
349Such allocations cannot be sanitized by
350.Nm .
351However, in some cases it may be possible to use
352.Fn kmsan_mark
353to manually annotate fields which are known to contain invalid data upon
354allocation.
355