brintos

brintos / linux-shallow public Read only

0
0
Text · 13.5 KiB · 910668e Raw
317 lines · plain
1======================2Kernel Self-Protection3======================4 5Kernel self-protection is the design and implementation of systems and6structures within the Linux kernel to protect against security flaws in7the kernel itself. This covers a wide range of issues, including removing8entire classes of bugs, blocking security flaw exploitation methods,9and actively detecting attack attempts. Not all topics are explored in10this document, but it should serve as a reasonable starting point and11answer any frequently asked questions. (Patches welcome, of course!)12 13In the worst-case scenario, we assume an unprivileged local attacker14has arbitrary read and write access to the kernel's memory. In many15cases, bugs being exploited will not provide this level of access,16but with systems in place that defend against the worst case we'll17cover the more limited cases as well. A higher bar, and one that should18still be kept in mind, is protecting the kernel against a _privileged_19local attacker, since the root user has access to a vastly increased20attack surface. (Especially when they have the ability to load arbitrary21kernel modules.)22 23The goals for successful self-protection systems would be that they24are effective, on by default, require no opt-in by developers, have no25performance impact, do not impede kernel debugging, and have tests. It26is uncommon that all these goals can be met, but it is worth explicitly27mentioning them, since these aspects need to be explored, dealt with,28and/or accepted.29 30 31Attack Surface Reduction32========================33 34The most fundamental defense against security exploits is to reduce the35areas of the kernel that can be used to redirect execution. This ranges36from limiting the exposed APIs available to userspace, making in-kernel37APIs hard to use incorrectly, minimizing the areas of writable kernel38memory, etc.39 40Strict kernel memory permissions41--------------------------------42 43When all of kernel memory is writable, it becomes trivial for attacks44to redirect execution flow. To reduce the availability of these targets45the kernel needs to protect its memory with a tight set of permissions.46 47Executable code and read-only data must not be writable48~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~49 50Any areas of the kernel with executable memory must not be writable.51While this obviously includes the kernel text itself, we must consider52all additional places too: kernel modules, JIT memory, etc. (There are53temporary exceptions to this rule to support things like instruction54alternatives, breakpoints, kprobes, etc. If these must exist in a55kernel, they are implemented in a way where the memory is temporarily56made writable during the update, and then returned to the original57permissions.)58 59In support of this are ``CONFIG_STRICT_KERNEL_RWX`` and60``CONFIG_STRICT_MODULE_RWX``, which seek to make sure that code is not61writable, data is not executable, and read-only data is neither writable62nor executable.63 64Most architectures have these options on by default and not user selectable.65For some architectures like arm that wish to have these be selectable,66the architecture Kconfig can select ARCH_OPTIONAL_KERNEL_RWX to enable67a Kconfig prompt. ``CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT`` determines68the default setting when ARCH_OPTIONAL_KERNEL_RWX is enabled.69 70Function pointers and sensitive variables must not be writable71~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~72 73Vast areas of kernel memory contain function pointers that are looked74up by the kernel and used to continue execution (e.g. descriptor/vector75tables, file/network/etc operation structures, etc). The number of these76variables must be reduced to an absolute minimum.77 78Many such variables can be made read-only by setting them "const"79so that they live in the .rodata section instead of the .data section80of the kernel, gaining the protection of the kernel's strict memory81permissions as described above.82 83For variables that are initialized once at ``__init`` time, these can84be marked with the ``__ro_after_init`` attribute.85 86What remains are variables that are updated rarely (e.g. GDT). These87will need another infrastructure (similar to the temporary exceptions88made to kernel code mentioned above) that allow them to spend the rest89of their lifetime read-only. (For example, when being updated, only the90CPU thread performing the update would be given uninterruptible write91access to the memory.)92 93Segregation of kernel memory from userspace memory94~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~95 96The kernel must never execute userspace memory. The kernel must also never97access userspace memory without explicit expectation to do so. These98rules can be enforced either by support of hardware-based restrictions99(x86's SMEP/SMAP, ARM's PXN/PAN) or via emulation (ARM's Memory Domains).100By blocking userspace memory in this way, execution and data parsing101cannot be passed to trivially-controlled userspace memory, forcing102attacks to operate entirely in kernel memory.103 104Reduced access to syscalls105--------------------------106 107One trivial way to eliminate many syscalls for 64-bit systems is building108without ``CONFIG_COMPAT``. However, this is rarely a feasible scenario.109 110The "seccomp" system provides an opt-in feature made available to111userspace, which provides a way to reduce the number of kernel entry112points available to a running process. This limits the breadth of kernel113code that can be reached, possibly reducing the availability of a given114bug to an attack.115 116An area of improvement would be creating viable ways to keep access to117things like compat, user namespaces, BPF creation, and perf limited only118to trusted processes. This would keep the scope of kernel entry points119restricted to the more regular set of normally available to unprivileged120userspace.121 122Restricting access to kernel modules123------------------------------------124 125The kernel should never allow an unprivileged user the ability to126load specific kernel modules, since that would provide a facility to127unexpectedly extend the available attack surface. (The on-demand loading128of modules via their predefined subsystems, e.g. MODULE_ALIAS_*, is129considered "expected" here, though additional consideration should be130given even to these.) For example, loading a filesystem module via an131unprivileged socket API is nonsense: only the root or physically local132user should trigger filesystem module loading. (And even this can be up133for debate in some scenarios.)134 135To protect against even privileged users, systems may need to either136disable module loading entirely (e.g. monolithic kernel builds or137modules_disabled sysctl), or provide signed modules (e.g.138``CONFIG_MODULE_SIG_FORCE``, or dm-crypt with LoadPin), to keep from having139root load arbitrary kernel code via the module loader interface.140 141 142Memory integrity143================144 145There are many memory structures in the kernel that are regularly abused146to gain execution control during an attack, By far the most commonly147understood is that of the stack buffer overflow in which the return148address stored on the stack is overwritten. Many other examples of this149kind of attack exist, and protections exist to defend against them.150 151Stack buffer overflow152---------------------153 154The classic stack buffer overflow involves writing past the expected end155of a variable stored on the stack, ultimately writing a controlled value156to the stack frame's stored return address. The most widely used defense157is the presence of a stack canary between the stack variables and the158return address (``CONFIG_STACKPROTECTOR``), which is verified just before159the function returns. Other defenses include things like shadow stacks.160 161Stack depth overflow162--------------------163 164A less well understood attack is using a bug that triggers the165kernel to consume stack memory with deep function calls or large stack166allocations. With this attack it is possible to write beyond the end of167the kernel's preallocated stack space and into sensitive structures. Two168important changes need to be made for better protections: moving the169sensitive thread_info structure elsewhere, and adding a faulting memory170hole at the bottom of the stack to catch these overflows.171 172Heap memory integrity173---------------------174 175The structures used to track heap free lists can be sanity-checked during176allocation and freeing to make sure they aren't being used to manipulate177other memory areas.178 179Counter integrity180-----------------181 182Many places in the kernel use atomic counters to track object references183or perform similar lifetime management. When these counters can be made184to wrap (over or under) this traditionally exposes a use-after-free185flaw. By trapping atomic wrapping, this class of bug vanishes.186 187Size calculation overflow detection188-----------------------------------189 190Similar to counter overflow, integer overflows (usually size calculations)191need to be detected at runtime to kill this class of bug, which192traditionally leads to being able to write past the end of kernel buffers.193 194 195Probabilistic defenses196======================197 198While many protections can be considered deterministic (e.g. read-only199memory cannot be written to), some protections provide only statistical200defense, in that an attack must gather enough information about a201running system to overcome the defense. While not perfect, these do202provide meaningful defenses.203 204Canaries, blinding, and other secrets205-------------------------------------206 207It should be noted that things like the stack canary discussed earlier208are technically statistical defenses, since they rely on a secret value,209and such values may become discoverable through an information exposure210flaw.211 212Blinding literal values for things like JITs, where the executable213contents may be partially under the control of userspace, need a similar214secret value.215 216It is critical that the secret values used must be separate (e.g.217different canary per stack) and high entropy (e.g. is the RNG actually218working?) in order to maximize their success.219 220Kernel Address Space Layout Randomization (KASLR)221-------------------------------------------------222 223Since the location of kernel memory is almost always instrumental in224mounting a successful attack, making the location non-deterministic225raises the difficulty of an exploit. (Note that this in turn makes226the value of information exposures higher, since they may be used to227discover desired memory locations.)228 229Text and module base230~~~~~~~~~~~~~~~~~~~~231 232By relocating the physical and virtual base address of the kernel at233boot-time (``CONFIG_RANDOMIZE_BASE``), attacks needing kernel code will be234frustrated. Additionally, offsetting the module loading base address235means that even systems that load the same set of modules in the same236order every boot will not share a common base address with the rest of237the kernel text.238 239Stack base240~~~~~~~~~~241 242If the base address of the kernel stack is not the same between processes,243or even not the same between syscalls, targets on or beyond the stack244become more difficult to locate.245 246Dynamic memory base247~~~~~~~~~~~~~~~~~~~248 249Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up250being relatively deterministic in layout due to the order of early-boot251initializations. If the base address of these areas is not the same252between boots, targeting them is frustrated, requiring an information253exposure specific to the region.254 255Structure layout256~~~~~~~~~~~~~~~~257 258By performing a per-build randomization of the layout of sensitive259structures, attacks must either be tuned to known kernel builds or expose260enough kernel memory to determine structure layouts before manipulating261them.262 263 264Preventing Information Exposures265================================266 267Since the locations of sensitive structures are the primary target for268attacks, it is important to defend against exposure of both kernel memory269addresses and kernel memory contents (since they may contain kernel270addresses or other sensitive things like canary values).271 272Kernel addresses273----------------274 275Printing kernel addresses to userspace leaks sensitive information about276the kernel memory layout. Care should be exercised when using any printk277specifier that prints the raw address, currently %px, %p[ad], (and %p[sSb]278in certain circumstances [*]).  Any file written to using one of these279specifiers should be readable only by privileged processes.280 281Kernels 4.14 and older printed the raw address using %p. As of 4.15-rc1282addresses printed with the specifier %p are hashed before printing.283 284[*] If KALLSYMS is enabled and symbol lookup fails, the raw address is285printed. If KALLSYMS is not enabled the raw address is printed.286 287Unique identifiers288------------------289 290Kernel memory addresses must never be used as identifiers exposed to291userspace. Instead, use an atomic counter, an idr, or similar unique292identifier.293 294Memory initialization295---------------------296 297Memory copied to userspace must always be fully initialized. If not298explicitly memset(), this will require changes to the compiler to make299sure structure holes are cleared.300 301Memory poisoning302----------------303 304When releasing memory, it is best to poison the contents, to avoid reuse305attacks that rely on the old contents of memory. E.g., clear stack on a306syscall return (``CONFIG_GCC_PLUGIN_STACKLEAK``), wipe heap memory on a307free. This frustrates many uninitialized variable attacks, stack content308exposures, heap content exposures, and use-after-free attacks.309 310Destination tracking311--------------------312 313To help kill classes of bugs that result in kernel addresses being314written to userspace, the destination of writes needs to be tracked. If315the buffer is destined for userspace (e.g. seq_file backed ``/proc`` files),316it should automatically censor sensitive values.317