kernel recompilation for better hardening

I have a vision now how to implement this.

Installation through dpkg isn’t great anyhow? That doesn’t handle version upgrades. For example if someone installed a 5.x kernel from backports, this package would still force dpkg install a hardened 4.x kernel for no reason. By using APT, we’d never attempt a downgrade / install a lower versioned kernel.

dpkg also doesn’t well handle dependencies. If there ever was a conflicting dependency, dpkg would wreck APT (broken dependencies) which then requires manual commands to resolve. APT often warns against such situations, with the option to abort etc. Also dpkg does not properly call triggers such as DKMS?

How this could be implemented…

Terminology:

  • real APT: (non-Whonix, non-Kicksecure, plain Debian APT. Just the normal APT that any Debian user is using.)
  • wrapped APT (wapt): a wrapper that stacks various plugins such as rapt or hdapt
  • restricted APT (rapt): as per apparmor-profile-everything
  • hdapt: runs usual real apt dist-upgarde, apt update, apt-dist upgrade again

Most of these scripts can be implemented standalone without much thought about the other scripts.

When APT runs, some script could call the compilation script. And then create a local APT repository. That local APT repository would then be used with APT for proper processing of dependencies and triggers.

/etc/apt/sources.list.d/hardened-kernel-local.list:

deb [trusted=yes] file:/path/to/local/repository local main contrib non-free

similar to https://github.com/Whonix/Whonix/blob/master/help-steps/create-local-temp-apt-repo

User runs apt (or apt-get). What actually happens (without need to tell the user) (fully auditable in source code or by reading the files on the disk), that rapt (restricted APT) is executed - only if that is installed. It then passes on to hdapt (hardened kernel APT). Doing a usual real apt dist-upgrade. hdapt would then run “apt update” again to load the local APT repository which contains the hardened kernel and run real apt dist-upgrade again.

with apparmor-profile-everything:

wapt → rapt → hdapt → real apt update → real apt dist-upgrade → real apt update → real apt dist-upgrade

without apparmor-profile-everything:

wapt → hdapt → real apt update → real apt dist-upgrade → real apt update → real apt dist-upgrade


From user perspective:

  • user runs sudo apt update: just only that happens as per usual
  • user runs sudo apt dist-upgrade: usual sudo apt dist-upgrade happens + sudo apt update (fetching local APT repository with hardened kernel only) → another sudo apt --yes dist-upgrade is performed

(Fetching local (from hard drive) APT repository will take just 1 second or so.)

Same in other words:

  • user runs sudo apt update: just only that happens as per usual
  • user runs sudo apt dist-upgrade: usual sudo apt dist-upgrade happens → maybe hardened-kernel package is upgraded, compiles a new kernel, updates the local APT repository → + maybe sudo apt update (fetching local APT repository with hardened kernel only) → maybe another sudo apt --yes dist-upgrade is performed

maybe meaning: only if necessary (hardened-kernel package was upgraded).


Another layer of complexity that I haven’t mentioned yet: uwt stream isolation wrapper. Also something wrapped apt has to handle.


Just an idea yet. Dunno how it will look when implemented. Seems kinda complex. And messing that up would break APT. Users could still always run apt-get.anondist-orig (real apt).

And all this trouble for what? So users can keep typing what they’re accustomed to: apt or apt-get

Maybe rather than taking on that complexity with wrapped apt, we should rather have a one time popup teaching users to use hdapt from now?

hdapt and hdapt-get? Or only 1? I guess not much of extra work for both.


Maybe better to finish developing the concept of stackable wrappers first before implementing this?


What do we do with Whonix default redistributed (downloadable) builds in future? Pre-compile a hardened kernel and then re-compile it at first boot? Or just install Debian default kernel and compile a hardened kernel at first boot before going online for the first time?

An interesting option would also be to compile both, a non-debug and a debug kernel during the build process. Install both. Boot non-debug kernel by default. Debug kernel could be booted by choosing it in grub boot menu. Would waste some disk space and increase VM image size though.

madaidan via Whonix Forum:

What if we disable debugfs in the kernel but enable it in our new debugging kernel config?

Not every user of this config will be using apparmor-profile-everything so I think we should do as much reasonable kernel hardening as possible regardless of apparmor. Any lost debugging functionality can easily be re-enabled with the --debug flag if the user needs it.

Agreed. Debug kernel is required anyhow. And hardened-kernel might be sooner to go through completion, calling for testers, installed by default. Also more likely to be used by others than apparmor-profile-everything.

2 Likes