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