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 August 10, 2021 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.Sh FUNCTIONS 112The 113.Fn kmsan_mark 114and 115.Fn kmsan_orig 116functions update 117.Nm 118shadow state. 119.Fn kmsan_mark 120marks an address range as valid or invalid according to the value of the 121.Va code 122parameter. 123The valid values for this parameter are 124.Dv KMSAN_STATE_INITED 125and 126.Dv KMSAN_STATE_UNINIT , 127which mark the range as initialized and uninitialized, respectively. 128For example, when a piece of memory is freed to a kernel allocator, it will 129typically have been marked initialized; before the memory is reused for a new 130allocation, the allocator should mark it as uninitialized. 131As another example, writes to host memory performed by devices, e.g., via DMA, 132are not intercepted by the sanitizer; to avoid false positives, drivers should 133mark device-written memory as initialized. 134For many drivers this is handled internally by the 135.Xr busdma 9 136subsystem. 137.Pp 138The 139.Fn kmsan_orig 140function updates 141.Dq origin 142shadow state. 143In particular, it associates a given uninitialized buffer with a memory type 144and code address. 145This is used by the 146.Nm 147runtime to track the source of uninitialized memory and is only for debugging 148purposes. 149See 150.Sx IMPLEMENTATION NOTES 151for more details. 152.Pp 153The 154.Fn kmsan_check 155function and its sub-typed siblings validate the shadow state of the region(s) 156of kernel memory passed as input parameters. 157If any byte of the input is marked as uninitialized, the runtime will generate 158a report. 159These functions are useful during debugging, as they can be strategically 160inserted into code paths to narrow down the source of uninitialized memory. 161They are also used to perform validation in various kernel I/O paths, helping 162ensure that, for example, packets transmitted over a network do not contain 163uninitialized kernel memory. 164.Fn kmsan_check 165and related functions also take a 166.Fa descr 167parameter which is inserted into any reports raised by the check. 168.Sh IMPLEMENTATION NOTES 169.Ss Shadow Maps 170The 171.Nm 172runtime makes use of two shadows of the kernel map. 173Each address in the kernel map has a linear mapping to addresses in the 174two shadows. 175The first, simply called the shadow map, tracks the state of the corresponding 176kernel memory. 177A non-zero byte in the shadow map indicates that the corresponding byte of 178kernel memory is uninitialized. 179The 180.Nm 181instrumentation automatically propagates shadow state as the contents of kernel 182memory are transformed and copied. 183.Pp 184The second shadow is called the origin map, and exists only to help debug 185reports from the sanitizer. 186To avoid false positives, 187.Nm 188does not raise reports for certain operations on uninitialized memory, such 189as copying or arithmetic. 190Thus, operations on uninitialized state which raise a report may be far removed 191from the source of the bug, complicating debugging. 192The origin map contains information which can help pinpoint the root cause of 193a particular 194.Nm 195report; when generating a report, the runtime uses state from the origin map 196to provide extra details. 197.Pp 198Unlike the shadow map, the origin map is not byte-granular, but consists of 4-byte 199.Dq cells . 200Each cell describes the corresponding four bytes of mapped kernel memory and 201holds a type and compressed code address. 202When kernel memory is allocated for some purpose, its origin is initialized 203either by the compiler instrumentation or by runtime hooks in the allocator. 204The type indicates the specific allocator, e.g., 205.Xr uma 9 , 206and the address provides the location in the kernel code where the memory was 207allocated. 208.Ss Assembly Code 209When 210.Nm 211is configured, the compiler will only emit instrumentation for C code. 212Files containing assembly code are left un-instrumented. 213In some cases this is handled by the sanitizer runtime, which defines 214wrappers for subroutines implemented in assembly. 215These wrappers are referred to as interceptors and handle updating 216shadow state to reflect the operations performed by the original 217subroutines. 218In other cases, C code which calls assembly code or is called from 219assembly code may need to use 220.Fn kmsan_mark 221to manually update shadow state. 222This is typically only necessary in machine-dependent code. 223.Pp 224Inline assembly is instrumented by the compiler to update shadow state 225based on the output operands of the code, and thus does not usually 226require any special handling to avoid false positives. 227.Ss Interrupts and Exceptions 228In addition to the shadow maps, the sanitizer requires some thread-local 229storage (TLS) to track initialization and origin state for function 230parameters and return values. 231The sanitizer instrumentation will automatically fetch, update and 232verify this state. 233In particular, this storage block has a layout defined by the sanitizer 234ABI. 235.Pp 236Most kernel code runs in a context where interrupts or exceptions may 237redirect the CPU to begin execution of unrelated code. 238To ensure that thread-local sanitizer state remains consistent, the 239runtime maintains a stack of TLS blocks for each thread. 240When machine-dependent interrupt and exception handlers begin execution, 241they push a new entry onto the stack before calling into any C code, and 242pop the stack before resuming execution of the interrupted code. 243These operations are performed by the 244.Fn kmsan_intr_enter 245and 246.Fn kmsan_intr_leave 247functions in the sanitizer runtime. 248.Sh EXAMPLES 249The following contrived example demonstrates some of the types of bugs 250that are automatically detected by 251.Nm : 252.Bd -literal -offset indent 253int 254f(size_t osz) 255{ 256 struct { 257 uint32_t bar; 258 uint16_t baz; 259 /* A 2-byte hole is here. */ 260 } foo; 261 char *buf; 262 size_t sz; 263 int error; 264 265 /* 266 * This will raise a report since "sz" is uninitialized 267 * here. If it is initialized, and "osz" was left uninitialized 268 * by the caller, a report would also be raised. 269 */ 270 if (sz < osz) 271 return (1); 272 273 buf = malloc(32, M_TEMP, M_WAITOK); 274 275 /* 276 * This will raise a report since "buf" has not been 277 * initialized and contains whatever data is left over from the 278 * previous use of that memory. 279 */ 280 for (i = 0; i < 32; i++) 281 if (buf[i] != '\0') 282 foo.bar++; 283 foo.baz = 0; 284 285 /* 286 * This will raise a report since the pad bytes in "foo" have 287 * not been initialized, e.g., by memset(), and this call will 288 * thus copy uninitialized kernel stack memory into userspace. 289 */ 290 copyout(&foo, uaddr, sizeof(foo)); 291 292 /* 293 * This line itself will not raise a report, but may trigger 294 * a report in the caller depending on how the return value is 295 * used. 296 */ 297 return (error); 298} 299.Ed 300.Sh SEE ALSO 301.Xr build 7 , 302.Xr busdma 9 , 303.Xr copyout 9 , 304.Xr KASAN 9 , 305.Xr uma 9 306.Rs 307.%A Evgeniy Stepanov 308.%A Konstantin Serebryany 309.%T MemorySanitizer: fast detector of uninitialized memory use in C++ 310.%J 2015 IEEE/ACM International Symposium on Code Generation and Optimization (CGO) 311.%D 2015 312.Re 313.Sh HISTORY 314.Nm 315was ported from 316.Nx 317and first appeared in 318.Fx 14.0 . 319.Sh BUGS 320Accesses to kernel memory outside of the kernel map are ignored by the 321.Nm 322runtime. 323In particular, memory accesses via the direct map are not validated. 324When memory is copied from outside the kernel map into the kernel map, 325that region of the kernel map is marked as initialized. 326When 327.Nm 328is configured, kernel memory allocators are configured to use the kernel map, 329and filesystems are configured to always map data buffers into the kernel map, 330so usage of the direct map is minimized. 331However, some uses of the direct map remain. 332This is a conservative policy which aims to avoid false positives, but it will 333mask bug in some kernel subsystems. 334.Pp 335On amd64, global variables and the physical page array 336.Va vm_page_array 337are not sanitized. 338This is intentional, as it reduces memory usage by avoiding creating 339shadows of large regions of the kernel map. 340However, this can allow bugs to go undetected by 341.Nm . 342.Pp 343Some kernel memory allocators provide type-stable objects, and code which uses 344them frequently depends on object data being preserved across allocations. 345Such allocations cannot be sanitized by 346.Nm . 347However, in some cases it may be possible to use 348.Fn kmsan_mark 349to manually annotate fields which are known to contain invalid data upon 350allocation. 351