kernel recompilation for better hardening

We can have a separate config for the workstation and gateway with audio disabled in the gateway config and enabled in the workstation config. Other things can be disabled/enabled for different configs in the future if needed.

1 Like

Following hulahoop’s advice, I made the compilation use all cores assigned to the VM, by running make deb-pkg -j 4 which seemed to speed up the process.

For the package, we can use make deb-pkg -j $(nproc) so we use all of the user’s cores.


Debian packaging is beyond me.

1 Like

Thinking about packaging.
Build kernel and upload to Whonix repository?
No compilation on user’s system for all users, right?

Maybe have to fork this:

git clone. Checkout correct branch or tag. Fork new branch. Add your custom config. Commit. Build.

Also change kernel package name. Update debian/changelog with higher (debian packaging) version number.

But would prefer a more lightweight solution.

Also needs to be fully non interactive building. No graphical make menu config. But Debian must have sorted that already.

Also don’t use kernel signing / module signing during build? Another layer of complexity. Only the usual repository signing as for any package.


I would prefer to compile it on the user’s system for better security but currently the config isn’t slim enough to do that. I’ve heard of people reducing kernel compilation time to about 10 minutes which would be wonderful.

No need. We can just create our own scripts that move a few files about, extracts the source, runs make deb-pkg and installs the packages. Much easier.

That was only needed to generate the full config out of the one I gave you (which removed unneeded lines for simplicity). is the full config and doesn’t require make menuconfig.

I didn’t think of that. We cannot store any private keys for signing on the user’s machine. Too risky.

If the kernel package is pre-compiled for users, the private key can be stored securely by whoever compiles it so users don’t need to worry about it too much.

Best option would be to get rid of the need for signing entirely which would require removing modules support.

1 Like

Signed kernel is also useful for verified boot (discussion), namely secure boot. But perhaps verified boot won’t rely on kernel signatures but rather checksums.

On the other hand, with apparmor-profile-everything manual modprobe by root user could be forbidden anyhow.

Which goes back to the discussion of disabling module load vs non-module load support.

At the moment not a blocker since:

Both non-trivial. Not sure if realistic at all?

Alright, let’s assume compile on the user’s system. I like that. However, I don’t have a solution yet.

I started working on a script. Initially just to ease my workflow but such things often become the basis for deployed scripts.


## Copyright (C) 2012 - 2018 ENCRYPTED SUPPORT LP <>
## See the file COPYING for copying conditions.

set -x

set -e

## TODO: This probably has to be converted to debian/control 'Build-Depends:'.
sudo apt-get --no-install-recommends --yes install linux-source build-essential libssl-dev libncurses-dev fakeroot libelf-dev

## TODO: Probably better using mktemp?

mkdir -p "$folder"

pushd "$folder"

tar -xaf /usr/src/linux-source-4.19.tar.xz


pushd "$folder"/linux-source-4.19/

xzcat /usr/src/linux-patch-4.19-rt.patch.xz | patch -p1


## TODO: path to .config
cp ./.config "$folder"/linux-source-4.19/

#pushd "$folder"/linux-source-4.19/

## No more need....
#make menuconfig

#make deb-pkg

It would not be difficult for me to finish that script. Package it. Even run make deb-pkg the kernel during the postinst phase of installation script.

However, there is one blocker. The script would be run by apt/dpkg. The package creation would be happening during the installation of a pacakge while apt/dpkg is running. The result of that script would be Debian packages. The problem is, it is not possible to (sanely) possilble install a deb package while dpkg is already running. And it is already running.

A few years I invented GitHub - adrelanos/apt-during-apt: but it’s a giant hack. I don’t like it at all.

Somehow we’d need to install the packages after apt finished installing/upgrading hardened-vm-kernel.

How do we do that? Replace /usr/bin/apt and /usr/bin/apt-get with a wrapper? Not easy/clean since APT is already wrapped by uwt. And there are no stackable wrappers yet:

Utilize /usr/local/bin/? Ship /usr/local/bin/apt and /usr/local/bin/apt-get? Not clean. Also firejail is already using /usr/local/bin/ so that could set up for later conflicts.

Don’t wrap APT and tell users to use wapt /usr/bin/wapt (wrapped apt) instead? WAPT apt could be a wrapper to run APT normally but before and after APT any number of hooks could be run. One such hook could be “if hardened-vm-kernel created new packages, install these at the end”. Cleaner but also not great as we’d have to reach users to use WAPT rather than APT and constantly explain this.

Are you sure? make menuconfig creates other files too. To see for yourself: put the linux source folder under git version control before running make menuconfig. Delete .gitignore. Run make menuconfig. It creates other files inside the source folder too.

1 Like
git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  deleted:    include/config/tristate.conf

Untracked files:
  (use "git add <file>..." to include in what will be committed)


no changes added to commit (use "git add" and/or "git commit -a")

Last time it was more files.

Maybe not important. Maybe done automatically during make deb-pkg.

1 Like

Could you please check the diff between your original kernel config and the one based on the Debian kernel config?

1 Like
make menuconfig
  HOSTCC  scripts/basic/fixdep
  UPD     scripts/kconfig/.mconf-cfg
  HOSTCC  scripts/kconfig/mconf.o
  YACC    scripts/kconfig/
  LEX     scripts/kconfig/zconf.lex.c
  HOSTCC  scripts/kconfig/
  HOSTCC  scripts/kconfig/lxdialog/checklist.o
  HOSTCC  scripts/kconfig/lxdialog/inputbox.o
  HOSTCC  scripts/kconfig/lxdialog/menubox.o
  HOSTCC  scripts/kconfig/lxdialog/textbox.o
  HOSTCC  scripts/kconfig/lxdialog/util.o
  HOSTCC  scripts/kconfig/lxdialog/yesno.o
  HOSTLD  scripts/kconfig/mconf
scripts/kconfig/mconf  Kconfig

*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.

Any of these files required?

1 Like

Using new VM and using - compilation failing.

user@debian-buster-standalone:~/kernel/linux-source-4.19$ make deb-pkg
make clean
/bin/bash ./scripts/package/mkdebian
  TAR     linux-4.19.67-rt24 -rt24 -rt24.tar.gz
tar: You may not specify more than one '-Acdtrux', '--delete' or  '--test-label' option
Try 'tar --help' or 'tar --usage' for more information.
make[1]: *** [scripts/package/Makefile:73: deb-pkg] Error 2
make: *** [Makefile:1374: deb-pkg] Error 2
1 Like

Above error does not happen with your old kernel config.

To automate “make menuconfig” just use make oldconfig instead?
(As per bash - How to script make menuconfig to automate Linux kernel build configuration? - Unix & Linux Stack Exchange)
Could that help to provide a shorter kernel .config file in the repository?

(Used old config + make oldconfig. Compilation in progress. Seems to be past that error.)

1 Like

I like this. Maybe reserve it exclusively for hardened kernel upgrade process instead of making it the default apt for Whonix? This can be an important message that belongs in the terminal.


@madaidan can you make sure CONFIG_TUN is included or else OpenVPN won’t work. Also while we’re at it, perhaps toggle processor specific optimization for faster runtime (if it doesn’t slow down build time too much)

1 Like

ccache should also be a nice speedup for repeated building in the future when upgrading (although I never managed to get it to work). I am not sure though if it can help when we are randomizing kernel structure for security - the code may be too different and require a re build instead of using the cached stuff. All this can be detected by benchmarking the build time.


Yes, those other files are just needed for configuring the config, not for the actual kernel.

That’s what is. There have been minor commits since though.

We can do that if you want. I don’t see any advantage though.

CONFIG_TUN is enabled. I haven’t touched much processor-related settings so if the default Debian config enables them, my one does too (I based it off the Debian config).

Just Ctrl + F for any other option to see if it’s there.


Have you updated the VM? It might be some outdated packages.

I think it’d be a better solution than messing with wrappers.

Why not just use the already existing apt-get-update-plus?

1 Like

Not Whonix specific indeed. Would be generic. Is that what you meant?

Which processor[s]?

Yes, unless something speaks against it. The idea is: smaller file size. Easier to review. And keeping auto generated code out of source code files.

No outdated packages.

apt-during-apt comes with grave disadvantages:

  • running in background, without user knowledge
  • upgrades might be interrupted. User might think upgrading is done but the systemd unit file might still be working in background.

It could lead to not upgrading the kernel when users use regular APT instead of apt-get-update-plus .

Another idea:
repurpose uwt from “use with Tor” to “ultimate wrapper tool”.
uwt adding stream isolation would just be one feature. Hooking apt for kernel upgrades another feature.


It might be easier to review with those # X is not needed lines as it allows someone to grep the config for a certain option to see if it is set or not. If it isn’t there, they might get confused and think that option doesn’t exist when in reality, we just removed those lines.

I’m not sure what the problem is then. I tested compilation just last night and it worked fine. Maybe it’s a missing dependency somewhere?

To debug, try strace make deb-pkg (requires kernel.yama.ptrace_scope=0 with sysctl first) and see if you can find any errors.

Aren’t users instructed to use apt-get-update-plus? Why should any other way of updating be supported?

This seems like an excellent idea. Especially considering apt is already using uwt.

1 Like

Good to know. We can apply it to kicksecure too. What I meant is that we make wapt usage an exception applied to select packages instead of the normal go-to command for installing/updating anything?

Makes sense - uwt could act as the backend while still invoking wrapped apt with the “wapt” name

1 Like