The CLIP OS kernel is based on Linux. It also integrates:
- existing hardening patches that are not upstream yet and that we consider relevant to our security model;
- developments made for previous CLIP OS versions that we have not upstreamed yet (or that cannot be);
- entirely new functionalities that have not been upstreamed yet (or that cannot be).
As the core of a hardened operating system, the CLIP OS kernel is particularly responsible for:
- providing robust security mechanisms to higher levels of the operating system, such as reliable isolation primitives;
- maintaining maximal trust in hardware resources;
- guaranteeing its own protection against various threats.
In this section we discuss our security-relevant configuration choices for the CLIP OS kernel. Before starting, it is worth mentioning that:
We do our best to limit the number of kernel modules.
In other words, as many modules as possible should be built-in. Modules are only used when needed either for the initramfs or to ease the automation of the deployment of CLIP OS on multiple different machines (for the moment, we only target a QEMU-KVM guest). This is particularly important as module loading is disabled after CLIP OS startup.
We focus on a secure configuration. The remaining of the configuration is minimal and it is your job to tune it for your machines and use cases.
CLIP OS only supports the x86-64 architecture for now.
Running 32-bit programs is voluntarily unsupported. Should you change that in your custom kernel, keep in mind that it requires further attention when configuring it (e.g., ensure that
Many options that are not useful to us are disabled in order to cut attack surface. As they are not all detailed below, please see
src/portage/clip/sys-kernel/clipos-kernel/files/config.d/blacklistfor an exhaustive list of the ones we explicitly disable.
CLIP OS will need the auditing infrastructure.
We do not need
.configto be available at runtime, neither do we need access to kernel headers through sysfs.
Asynchronous I/O mostly targets high-performance applications. It brings a lot of complexity and increases the kernel attack surface.
Symbols are only useful for debug and attack purposes.
Remove the BPF interpreter to avoid speculative execution of BPF instructions. See also the
userfaultfd()system call adds attack surface and can make heap sprays easier. Note that the
vm.unprivileged_userfaultfdsysctl can also be used to restrict the use of this system call to privileged users.
This unlocks additional configuration options we need.
User namespaces can be useful for some use cases but even more to an attacker. We choose to disable them for the moment, but we could also enable them and use the
kernel.unprivileged_userns_clonesysctl provided by linux-hardened to disable their unprivileged use.
Allow allocator validation checking to be enabled.
Merging SLAB caches can make heap exploitation easier.
Randomize allocator freelists
Harden slab metadata
Place canaries at the end of slab allocations. [linux-hardened]
Page allocator randomization is primarily a performance improvement for direct-mapped memory-side-cache utilization, but it does reduce the predictability of page allocations and thus complements
page_alloc.shuffle=1parameter needs to be added to the kernel command line.
Enabling this would disable brk ASLR.
Enable GCC plugins, some of which are security-relevant; GCC 4.7 at least is required.
Instrument some kernel code to gather additional (but not cryptographically secure) entropy at boot time.
Prevent potential information leakage by forcing zero-initialization of:
- structures on the stack containing userspace addresses;
- any stack variable (thus including structures) that may be passed by reference and has not already been explicitly initialized.
This is particularly important to prevent trivial bypassing of KASLR.
Randomize layout of sensitive kernel structures. Exploits targeting such structures then require an additional information leak vulnerability.
Do not weaken structure randomization
Use maximum number of randomized bits for the mmap base address on x86_64. Note that thanks to a linux-hardened patch, this also impacts the number of randomized bits for the stack base address.
-fstack-protector-strongfor best stack canary coverage; GCC 4.9 at least is required.
Virtually-mapped stacks benefit from guard pages, thus making kernel stack overflows harder to exploit.
Enforce strict memory mappings permissions for loadable kernel modules.
Although CLIP OS stores kernel modules in a read-only rootfs whose integrity is guaranteed by dm-verity, we still enable and enforce module signing as an additional layer of security:
This option requires compiler support that is currently only available in Clang.
Processor type and features¶
Retpolines are needed to protect against Spectre v2. GCC 7.3.0 or higher is required.
The vsyscall table is not required anymore by libc and is a fixed-position potential source of ROP gadgets.
Machine Check Exceptions can report suspicious hardware errors, some of which may for instance, on systems with ECC memory, reveal an ongoing Rowhammer attack.
ioperm(2)system calls, which should not be used by modern userspace anymore.
Needed to benefit from microcode updates and thus security fixes (e.g., additional Intel pseudo-MSRs to be used by the kernel as a mitigation for various speculative execution vulnerabilities).
Enabling those features would only present userspace with more attack surface.
We do not use memory hot-add and it makes memory management code more complex.
Enabling this feature can make cache side-channel attacks such as FLUSH+RELOAD much easier to carry out.
This should in particular be non-zero to prevent the exploitation of kernel NULL pointer bugs.
Memory Type Range Registers can make speculative execution bugs a bit harder to exploit.
Page Attribute Tables are the modern equivalents of MTRRs, which we described above.
Enable the RDRAND instruction to benefit from a secure hardware RNG if supported. See also
Enable Supervisor Mode Access Prevention to prevent ret2usr exploitation techniques.
Enable User Mode Instruction Prevention to prevent some instructions that unnecessarily expose information about the hardware state from being executed in user mode.
Intel Memory Protection Extensions (MPX) add hardware assistance to memory protection. Compiler support is required but was deprecated in GCC 8 and removed from GCC 9. Moreover, MPX kernel support is being dropped.
Memory Protection Keys are a promising feature but they are still not supported on current hardware.
Set the default value of the
tsxkernel parameter to
Enable the seccomp BPF userspace API for syscall attack surface reduction:
While this may be seen as a controversial feature, it makes sense for CLIP OS. Indeed, KASLR may be defeated thanks to the kernel interfaces that are available to an attacker, or through attacks leveraging hardware vulnerabilities such as speculative and out-of-order execution ones. However, CLIP OS follows the defense in depth principle and an attack surface reduction approach. Thus, the following points make KASLR relevant in the CLIP OS kernel:
- KASLR was initially designed to counter remote attacks but the strong security model of CLIP OS (e.g., no sysfs mounts in most containers, minimal procfs, no arbitrary code execution) makes a local attack more complex to carry out.
- STRUCTLEAK, STACKLEAK, kptr_restrict and
CONFIG_SECURITY_DMESG_RESTRICTare enabled in CLIP OS.
- The CLIP OS kernel is custom-compiled (at least for a given deployment), its image is unreadable to all users including privileged ones and updates are end-to-end encrypted. This makes both the content and addresses of the kernel image secret. Note that, however, the production kernel image is currently part of an EFI binary and is not encrypted, causing it to be accessible to a physical attacker. This will change in the future as we will only use the kernel included in the EFI binary to boot and then kexec to the real production kernel whose image will be located on an encrypted disk partition.
- We enable
CONFIG_PANIC_ON_OOPSby default so that the kernel cannot recover from failed exploit attempts, thus preventing any brute forcing.
- We enable Kernel Page Table Isolation, mitigating Meltdown and potential other hardware information leakage. Variante 3a (Rogue System Register Read) however remains an important threat to KASLR.
Most of the above explanations stand for that feature.
kexec()system call to prevent an already-root attacker from rebooting on an untrusted kernel.
A crash dump can potentially provide an attacker with useful information. However we disabled
kexec()syscalls above thus this configuration option should have no impact anyway.
This is not supposed to be needed by userspace applications and only increases the kernel attack surface.
Power management and ACPI options¶
The CLIP OS swap partition is encrypted with an ephemeral key and thus cannot support suspend to disk.
Do not provide means to upgrade arbitrary ACPI tables. Note that even if enabled, this functionality is restricted by
In order to work properly, this mitigation requires userspace support that is currently not available in CLIP OS. Moreover, due to our use of Secure Boot, Trusted Boot and the fact that machines running CLIP OS are expected to lock their BIOS with a password, the type of cold boot attacks this mitigation is supposed to thwart should not be an issue.
Prevent any malicious PCI device from performing DMA attacks while the IOMMU is disabled as part of the handover from system firmware to kernel.
Do not provide means to load arbitrary ACPI tables.
The vhost protocol offloads the virtio dataplane implementation to the kernel. This reduces isolation of virtual machines, by getting rid of the existing protocol break and increasing the host kernel attack surface.
Executable file formats / Emulations¶
We do not want our kernel to support miscellaneous binary classes. ELF binaries and interpreted scripts starting with a shebang are enough.
Core dumps can provide an attacker with useful information.
Enable TCP syncookies.
Disable TCP simultaneous connect, which is a weakness in Linux’s implementation of TCP that could be used by an attacker to disturb certain connections. This actually sets the default value of the
Expose the TPM’s Random Number Generator (RNG) as a Hardware RNG (HWRNG) device, allowing the kernel to collect randomness from it. See documentation of
rng_core.default_qualitycommand line parameter for supplementary information.
CLIP OS leverages the TPM to ensure boot integrity.
/dev/memdevice should not be required by any user application nowadays.
If you must enable it, at least enable
CONFIG_IO_STRICT_DEVMEMto restrict at best access to this device.
This virtual device is only useful for debug purposes and is very dangerous as it allows direct kernel memory writing (particularly useful for rootkits).
Use the modern PTY interface only.
Do not automatically load any line discipline that is in a kernel module when an unprivileged user asks for it.
/dev/portdevice should not be used anymore by userspace, and it could increase the kernel attack surface.
Do not credit entropy included in Linux’s entropy pool when generated by the CPU manufacturer’s HWRNG, the bootloader or the UEFI firmware. Fast and robust initialization of Linux’s CSPRNG is instead achieved thanks to the TPM’s HWRNG (see documentation of
rng_core.default_qualitycommand line parameter).
Disable old drivers with unfixable security holes.
Staging drivers are typically of lower quality and under heavy development. They are thus more likely to contain bugs, including security vulnerabilities, and should be avoided.
The IOMMU allows for protecting the system’s main memory from arbitrary accesses from devices (e.g., DMA attacks). Note that this is related to hardware features. On a recent Intel machine, we enable the following:
Enabling this would provide an attacker with precious information on the running kernel.
This should only be needed for debugging.
This is useful even in a production kernel to enable further configuration options that have security benefits.
Enable sanity checks in virtual to page code.
Ensure kernel page tables have strict permissions.
Check and report any dangerous memory mapping permissions, i.e., both writable and executable kernel pages.
The debugfs virtual file system is only useful for debugging and protecting it would require additional work.
slub_debugcommand line parameter provides more fine grained control.
Prevent potential further exploitation of a bug by immediately panicking the kernel.
The following options add additional checks and validation for various commonly targeted kernel structures:
Note that linux-hardened patches add more places where this configuration option has an impact.
We choose to poison pages with zeroes and thus prefer using
init_on_freein combination with linux-hardened’s
Prevent unprivileged users from gathering information from the kernel log buffer via
dmesg(8). Note that this still can be overridden through the
Enable KPTI to prevent Meltdown attacks and, more generally, reduce the number of hardware side channels.
CLIP OS does not use Intel Trusted Execution Technology.
Harden data copies between kernel and user spaces, preventing classes of heap overflow exploits and information leaks.
Use strict whitelisting mode, i.e., do not
Leverage compiler to detect buffer overflows.
FORTIFY_SOURCEto intra-object overflow checking. It is useful to find bugs but not recommended for a production kernel yet. [linux-hardened]
This makes the kernel route all usermode helper calls to a single binary that cannot have its name changed. Without this, the kernel can be tricked into calling an attacker-controlled binary (e.g. to bypass SMAP, cf. exploitation of CVE-2016-8655).
Currently, we have no need for usermode helpers therefore we simply disable them. If we ever need some, this path will need to be set to a custom trusted binary in charge of filtering and choosing what real helpers should then be called.
Enable us to choose different security modules.
CLIP OS intends to leverage SELinux in its security model.
We do not need SELinux to be disableable.
We do not want SELinux to be disabled. In addition, keeping this option off makes LSM structures such as security hooks read-only.
For now, but will eventually be
Basically, the lockdown LSM tries to strengthen the boundary between the superuser and the kernel. The integrity mode thus restricts access to features that would allow userland to modify the running kernel, and the confidentiality mode extends these restrictions to features that would allow userland to extract confidential information held inside the kernel. Note that a significant portion of such features is already disabled in the CLIP OS kernel due to our custom configuration. The lockdown functionality is important for CLIP OS as we want to prevent an attacker, be he highly privileged, from persisting on a compromised machine.
SELinux shall be stacked too once CLIP OS uses it.
The Yama LSM currently provides ptrace scope restriction (which might be redundant with CLIP-LSM in the future).
The integrity subsystem provides several components, the security benefits of which are already enforced by CLIP OS (e.g., read-only mounts for all parts of the system containing executable programs).
See documentation about the
kernel.perf_event_paranoidsysctl below. [linux-hardened]
This prevents unprivileged users from using the TIOCSTI ioctl to inject commands into other processes that share a tty session. [linux-hardened]
STACKLEAK erases the kernel stack before returning from system calls,
leaving it initialized to a poison value. This both reduces the information
that kernel stack leak bugs can reveal and the exploitability of uninitialized
stack variables. However, it does not cover functions reaching the same stack
depth as prior functions during the same system call.
It used to also block kernel stack depth overflows caused by
as Stack Clash attacks. We maintained this functionality for our kernel for a
while but eventually dropped it.
init_on_alloc=1on the kernel command line. See the documentation of these kernel parameters for details.
Verify that newly allocated pages and slab allocations are zeroed to detect write-after-free bugs. This works in concert with
init_on_freeand is adjusted to not be redundant with
GCC version 7.3.0 or higher is required to fully benefit from retpolines
Sysctl Security Tuning¶
Many sysctls are not security-relevant or only play a role if some kernel configuration options are enabled/disabled. In other words, the following is tightly related to the CLIP OS kernel configuration detailed above.
dev.tty.ldisc_autoload = 0
CONFIG_LDISC_AUTOLOADabove, which serves as a default value for this sysctl.
kernel.kptr_restrict = 2
Hide kernel addresses in
/procand other interfaces, even to privileged users.
kernel.yama.ptrace_scope = 3
Enable the strictest ptrace scope restriction provided by the Yama LSM.
kernel.perf_event_paranoid = 3
This completely disallows unprivileged access to the
perf_event_open()system call. This is actually not needed as we already enable
Note that this requires a patch included in linux-hardened (see here for the reason why it is not upstream). Indeed, on a mainline kernel without such a patch, the above is equivalent to setting this sysctl to
2, which would still allow the profiling of user processes.
kernel.tiocsti_restrict = 1
This is already forced by the
CONFIG_SECURITY_TIOCSTI_RESTRICTkernel configuration option that we enable. [linux-hardened]
The following two sysctls help mitigating TOCTOU vulnerabilities by preventing users from creating symbolic or hard links to files they do not own or have read/write access to:
fs.protected_symlinks = 1
fs.protected_hardlinks = 1
In addition, the following other two sysctls impose restrictions on the opening of FIFOs and regular files in order to make similar spoofing attacks harder (note however that these restrictions currently do not apply to networked filesystems, among others):
fs.protected_fifos = 2
fs.protected_regular = 2
We do not simply disable the BPF Just in Time compiler as CLIP OS plans on using it:
kernel.unprivileged_bpf_disabled = 1
Prevent unprivileged users from using BPF.
net.core.bpf_jit_harden = 2
Trades off performance but helps mitigate JIT spraying.
kernel.deny_new_usb = 0
The management of USB devices is handled at a higher level by CLIP OS. [linux-hardened]
kernel.device_sidechannel_restrict = 1
Restrict device timing side channels. [linux-hardened]
fs.suid_dumpable = 0
Do not create core dumps of setuid executables. Note that we already disable all core dumps by setting
kernel.pid_max = 65536
Increase the space for PID values.
kernel.modules_disabled = 1
Disable module loading once systemd has loaded the ones required for the running machine according to a profile (i.e., a predefined and hardware-specific list of modules).
Pure network sysctls (
net.ipv6.*) will be detailed in a
Command line parameters¶
We pass the following command line parameters to the kernel:
This parameter provided by a linux-hardened patch (based on the PaX implementation) enables a very simple form of latent entropy extracted during system start-up and added to the entropy obtained with
This force-enables KPTI even on CPUs claiming to be safe from Meltdown.
Same reasoning as above but for the Spectre v2 vulnerability. Note that this implies
spectre_v2_user=on, which enables the mitigation against user space to user space task attacks (namely IBPB and STIBP when available and relevant).
Same reasoning as above but for the Spectre v4 vulnerability. Note that this mitigation requires updated microcode for Intel processors.
This parameter controls optional mitigations for the Microarchitectural Data Sampling (MDS) class of Intel CPU vulnerabilities. Not specifying this parameter is equivalent to setting
mds=full, which leaves SMT enabled and therefore is not a complete mitigation. Note that this mitigation requires an Intel microcode update and also addresses the TSX Asynchronous Abort (TAA) Intel CPU vulnerability on systems that are affected by MDS.
Even if we correctly enable the IOMMU in the kernel configuration, the kernel can still decide for various reasons to not initialize it at boot. Therefore, we force it with this parameter. Note that with some Intel chipsets, you may need to add
intel_iommu=igfx_offto allow your GPU to access the physical memory directly without going through the DMA Remapping.
Foption adds many sanity checks to various slab operations. Other interesting options that we considered but eventually chose to not use are:
Poption, which enables poisoning on slab cache allocations, disables the
SLAB_SANITIZE_VERIFYfeatures. As they respectively poison with zeroes on object freeing and check the zeroing on object allocations, we prefer enabling them instead of using
Zoption enables red zoning, i.e., it adds extra areas around slab objects that detect when one is overwritten past its real size. This can help detect overflows but we already rely on
SLAB_CANARYprovided by linux-hardened. A canary is much better than a simple red zone as it is supposed to be random.
This makes the system always panic on uncorrected errors reported by the Machine Check support. Otherwise, some of them may only cause a SIGBUS to be sent, potentially allowing a malicious process to keep trying to exploit a hardware bug like Rowhammer.
Increase trust in the TPM’s HWRNG to robustly and fastly initialize Linux’s CSPRNG by crediting half of the entropy it provides.
Also, note that:
slub_nomergeis not used as we already set
CONFIG_SLAB_MERGE_DEFAULT=nin the kernel configuration.
l1tf: The built-in PTE Inversion mitigation is sufficient to mitigate the L1TF vulnerability as long as CLIP OS is not used as an hypervisor with untrusted guest VMs. If it were to be someday,
l1tf=full,forceshould be used to force-enable VMX unconditional cache flushes and force-disable SMT (note that an Intel microcode update is not required for this mitigation to work but improves performance by providing a way to invalidate caches with a finer granularity).
tsx=off: This parameter is already set by default thanks to
CONFIG_X86_INTEL_TSX_MODE_OFF. It deactivates the Intel TSX feature on CPUs that support TSX control (i.e. are recent enough or received a microcode update) and that are not already vulnerable to MDS, therefore mitigating the TSX Asynchronous Abort (TAA) Intel CPU vulnerability.
tsx_async_abort: This parameter controls optional mitigations for the TSX Asynchronous Abort (TAA) Intel CPU vulnerability. Due to our use of
mds=full,nosmtin addition to
CONFIG_X86_INTEL_TSX_MODE_OFF, CLIP OS is already protected against this vulnerability as long as the CPU microcode has been updated, whether or not the CPU is affected by MDS. For the record, if we wanted to keep TSX activated, we could specify
tsx_async_abort=full,nosmt. Not specifying this parameter is equivalent to setting
tsx_async_abort=full, which leaves SMT enabled and therefore is not a complete mitigation. Note that this mitigation requires an Intel microcode update and has no effect on systems that are already affected by MDS and enable mitigations against it, nor on systems that disable TSX.
kvm.nx_huge_pages: This parameter allows to control the KVM hypervisor iTLB multihit mitigations. Such mitigations are not needed as long as CLIP OS is not used as an hypervisor with untrusted guest VMs. If it were to be someday,
kvm.nx_huge_pages=forceshould be used to ensure that guests cannot exploit the iTLB multihit erratum to crash the host.
mitigations: This parameter controls optional mitigations for CPU vulnerabilities in an arch-independent and more coarse-grained way. For now, we keep using arch-specific options for the sake of explicitness. Not setting this parameter equals setting it to
auto, which itself does not update anything.
init_on_free=1is automatically set due to
INIT_ON_FREE_DEFAULT_ON. It zero-fills page and slab allocations on free to reduce risks of information leaks and help mitigate a subset of use-after-free vulnerabilities.
init_on_alloc=1is automatically set due to
INIT_ON_ALLOC_DEFAULT_ON. The purpose of this functionality is to eliminate several kinds of uninitialized heap memory flaws by zero-filling:
- all page allocator and slab allocator memory when allocated: this is
already guaranteed by our use of
init_on_freein combination with
SLAB_SANITIZE_VERIFYfrom linux-hardened, and thus has no effect;
- a few more special objects when allocated: these are the ones for which
init_on_allocas they are not covered by the aforementioned combination of
- all page allocator and slab allocator memory when allocated: this is already guaranteed by our use of
efi=disable_early_pci_dmais not used as we already set
CONFIG_EFI_DISABLE_PCI_DMA=yin the kernel configuration.
Citations and origin of some items
|[linux-hardened]||(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) This item is provided by the |