We might want to set our sysctl values in earlier boot to better defend the system against rootkits that run before systemd-sysctl is executed.
For example: rootkit executes before kptr_restrict is set → gets access to kernel symbols → can now use those for kernel exploits
Or, even worse: rootkit executes before kexec_load_disabled is set → replaces the running kernel with a malicious kernel
apparmor-profile-everything will prevent the attacker from changing the sysctls themselves so that’s not a problem. The problem is if the attacker manages to launch attacks before they are changed to our safer settings.
I don’t see how that would be possible. Would require installing a systemd unit file or initramfs hook which is already prevented by apparmor-profile-everything.
That sounds really inflexible. Maybe a better idea…
Can you submit a patch to kernel.org or linux-hardened which adds a kernel boot parameter ldsysctl “Lock Down Sysctl” (or better name) which makes sysctl read-only after having set those? I.e. a kernel boot parameter which enforces that sysctl can be initially set but the not changed again?
Since apparmor-profile-everything confines even systemd, our threat model would include preventing a compromised init from attacking the kernel.
Seems a challenge usability wise. Possible issues:
Hardcoded, hard to change sysctl settings, inflexible.
Unexpected by users that there are sysctl settings in initramfs.
Difficult to change sysctl settings in initramfs.
Different settings in initramfs sysctl vs rootfs sysctl creating
strange, hard to debug situations.
This could consist of various components.
sysctl-to-initrd (or so): An initramfs hook which copies /etc/sysctl and /etc/sysctl.d (/etc/sysctl(.d)) to initramfs. The
rootfs /etc/sysctl(.d) would be considered the prime source. initramfs /etc/sysctl(.d) would be cleanly created from /etc/sysctl(.d) at
a dpkg trigger that runs when dpkg modified any files in /etc/sysctl(.d) (activate-noawait update-initramfs) (See existing
Whonix source code for that.) (I can probably do that.)
a systemd unit file that runs on shutdown which re-runs update-initramfs -u. But only if needed to save re-creating initramfs
every time. Re-creating initramfs every time non-conditionally increases
the risk of unclean shutdown of breaking the system and increases
maybe better than a systemd unit file would be a inotifywait based
solution that monitors changes to /etc/sysctl(.d)? Less chance of
unclean shutdown and destroying initramfs. See whonix-firewall /usr/lib/whonix-firewall/firewall-restarter for example use of inotifywait. (I can probably do that.) (inotifywait must not
conflict with the dpkg trigger.)
Initially initramfs-tools based only. Keeping it generic enough so later
support for dracut can be added.
What do you think?
While we are at it, before creating more and more initramfs integration,
are there good reasons to port from initramfs-tools to dracut anyhow? It
would be better to do this sooner than later if there are good reasons
to avoid having to re-implement things later. See also:
I probably could, but sysctls are sprawled all over the kernel source and making all of them read-only would be hard to do and maintaining it would also be hard.
Shouldn’t setting a sysctl be done through an API / function? Then
perhaps only the relevant function would need to be patched for ldsysctl?
Sounds good, but instead of continuously regenerating the initramfs, maybe we can apply the sysctl settings after the real rootfs has been mounted e.g.
sysctl -p /new_root/etc/sysctl.d/*.conf
This is of course A LOT better. The implementation stays contained
inside initramfs, no re-generation of initramfs, faster, no unclean
shutdown issue, no de-sync of rootfs sysctl vs initramfs sysctl.
Superadmin could still change sysctl and these would be consistent both,
rootfs sysctl and initramfs sysctl. No usability issue since users don’t
need to remember this when changing sysctl. Awesome! Please implement.
Only for non-root users. Run strace as root and it works fine.
Setting ptrace_scope to 2 restricts ptrace to root only, setting it to 3 denies access to ptrace entirely.
This would still be useful regardless if apparmor-profile-everything is used.
It would be preferable if it sets ptrace_scope to 2 as that still allows ptrace but only for root. ptrace is really dangerous is it gives malware an easy way to compromise any program in a user’s session. Disabling ptrace_scope wouldn’t be the best.
kernel.sysrq=1 is not the default. Dunno what Debian sets it to though.
A package debug which isn’t installed by default is a tool which must be as useful as possible for me. In past there was a situation where I needed to use strace to debug an application which should not be run as root (GUI application). Installing a debug package and then still needing to fiddle more (relax more settings) seems not useful for me. In Linux Kernel Runtime Guard (LKRG) - Linux Kernel Runtime Integrity Checking and Exploit Detection - #26 by Patrick I experienced a hard to debug issue which required serial console and SysRq. It wasn’t easy to set up a debug environment to gather any useful output. If it’s already hard for me as a developer, than I can only imagine how hard it would be for advanced users or new developers trying to debug something. Therefore there need to be strong development tools. A trigger someone can pull (superroot) sudo apt install debug to have access to unrestricted debugging. To debug something isn’t the most visible, rewarding task anyhow but having roadblocks on the way makes it even less likely someone could be bothered to look.
Could you please also process /etc/sysctl.conf? I personally don’t
like /etc/sysctl.conf file since there is /etc/sysctl.d folder but
this is required for consistency. /etc/sysctl.conf is still used by
many sysadmins and in many security guides.
Should we disable the systemd-sysctl service and apparmor profile in apparmor-profile-everything now?
I don’t know. Does that that work? The less code, the better. I guess
it’s no longer needed since no sysctl would be changed anyhow since
these get applied even already in initial ramdisk? systemd-sysctl trying
to re-enforce already existing settings wouldn’t require any permissions?
On the other hand, is it OK to say apparmor-profile-everything depends
on security-misc? Would that be the case?