Hello Linux Gurus,
I am seeking divine inspiration.
I don’t understand the apparent lack of hypervisor-based kernel protections in desktop Linux. It seems there is a significant opportunity for improvement beyond the basics of KASLR, stack canaries, and shadow stacks. However, I don’t see much work in this area on Linux desktop, and people who are much smarter than me develop for the kernel every day yet have not seen fit to produce some specific advanced protections at this time that I get into below. Where is the gap in my understanding? Is this task so difficult or costly that the open source community cannot afford it?
Windows PCs, recent Macs, iPhones, and a few Android vendors such as Samsung run their kernels atop a hypervisor. This design permits introspection and enforcement of security invariants from outside or underneath the kernel. Common mitigations include protection of critical data structures such as page table entries, function pointers, or SELinux decisions to raise the bar on injecting kernel code. Hypervisor-enforced kernel integrity appears to be a popular and at least somewhat effective mitigation although it doesn’t appear to be common on desktop Linux despite its popularity with other OSs.
Meanwhile, in the desktop Linux world, users are lucky if a distribution even implements secure boot and offers signed kernels. Popular software packages often require short-circuiting this mechanism so the user can build and install kernel modules, such as NVidia and VirtualBox drivers. SELinux is uncommon, ergo root access is more or less equivalent to the kernel privileges including introduction of arbitrary code into the kernel on most installations. TPM-based disk encryption is only officially supported experimentally by Ubuntu and is usually linked to secure boot, while users are largely on their own elsewhere. Taken together, this feels like a missed opportunity to implement additional defense-in-depth.
It’s easy to put code in the kernel. I can do it in a couple of minutes for a “hello world” module. It’s really cool that I can do this, but is it a good idea? Shouldn’t somebody try and stop me?
Please insert your unsigned modules into my brain-kernel. What have I failed to understand, or why is this the design of the kernel today? Is it an intentional omission? Is it somehow contrary to the desktop Linux ethos?
if you don’t want modules, you can compile a monolithic kernel. i have done so for a few years. it saves time if you run something like gentoo or LFS, because you don’t need an initrd and no mechanisms for loading modules. it has the downside of not being able to change some parameters during runtime, ie. you have to reboot and pass different parameters via booloader. you can then also switch off support for loading modules.
Ah, yes, I do enjoy spending 6 months rebuilding my daily driven car in the garage because the air filter is integrated deep in the engine and not easily replaceable.
The whole “I compile all my linux from source” might work if you are an IT major or have a lot of free time you can devote to maintaining your PC, but the majority of people that use a PC do not have the time, skill, attention span, or knowledge to do any more than press “Easy” and let the system have at it.
i just read there is even some kind of macro for switching all modules to built-in:
make mod2yesconfig # and/or make localyesconfig
compiling a kernel from the provided source is surprisingly easy tho. you can start with the default config from your distro, just toggle the options you want different in the menuconfig and compile it. there are howtos. also, once a pro has done it, they can share the config for others with similar setups.
if you fail and your kernel is broken, you can just use the old one again until you get it right. just don’t overwrite the old one when putting it where the boot loader is looking for it and give the new one it’s own boot loader entry.
This is interesting especially in embedded, and it’s a way to make loading code harder because now the kernel may not even have a facility for loading code. This does go in the right direction. Not even root can do it if there just isn’t code to load a module.
But, many if not most popular OSs go a step further and inspect the kernel to make sure it isn’t adding code to itself to the maximum extent possible, even if it were exploited by a bug.
i just read there is even some kind of macro for switching all modules to built-in:
make mod2yesconfig # and/or make localyesconfig
Also, the module blacklist file may accept wildcards, so you can blacklist all modules. And there is a sysctl switch “kernel.modules_disabled”, which lets you switch module changes off and on as required. Then again, an attacker who gained root to load modules could also re-enable it and de-blacklist his modules; so this is a lot weaker.
//edit: the blacklist is useless for security, because it only affects easy module loading with modprobe, not using insmod what an attacker would use.