Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Make DKMS sign kernel modules on installation, with full script support and somewhat distro independent

On systems with UEFI Secure Boot enabled, recent Linux kernels will only load signed modules, so it's about time DKMS grew the capability to sign modules it's building.

These scripts are extended and scriptified variants of https://computerlinguist.org/make-dkms-sign-kernel-modules-for-secure-boot-on-ubuntu-1604.html and https://askubuntu.com/questions/760671/could-not-load-vboxdrv-after-upgrade-to-ubuntu-16-04-and-i-want-to-keep-secur/768310#768310 and add some error checking, a passphrase around your signing key, and support for compressed modules.

dkms-sign-module is a wrapper for the more generic sign-modules which can also be used outside of DKMS.

Installation

  1. Create a directory under /root, say /root/module-signing, put the three scripts below in there and make them executable: chmod u+x one-time-setup sign-modules dkms-sign-module
  2. Run one-time-setup
  3. Reboot your computer to deploy the MOK
  4. For each module you will want to sign via DKMS, create a file /etc/dkms/<module_name>.conf with the following content:
    POST_BUILD=../../../../../../root/module-signing/dkms-sign-module
    
    The awkward relative pathname is important since DKMS prepends its own path to it, so an absolute path will not work.
#!/bin/bash
export PROMPT="Enter Machine Owner Key (MOK) passphrase to sign $module $module_version: "
export KERNELVER=$kernelver
$(dirname $0)/sign-modules ../$kernelver/$arch/module/*.ko*
#!/bin/bash
mydir=$(dirname $0)
echo "I am about to generate the Machine Owner Key (MOK)."
echo "The passphrase you enter for this key will be required every time you want to sign a module."
read -p "Please press Return to go on..."
openssl req -new -x509 -newkey rsa:2048 -keyout $mydir/MOK.priv -outform DER -out $mydir/MOK.der -days 36500 -subj "/CN=$(hostname) module signing key/" || exit 1
echo
echo "Now I will import the generated key into the secure keystore."
echo "The passphrase you will enter is only required once, during the following reboot."
read -p "Please press Return to go on..."
mokutil --import $mydir/MOK.der || exit 1
echo
echo "Please reboot your computer now to complete the enrollment of your new MOK."
echo "This is going to look somewhat similar to https://sourceware.org/systemtap/wiki/SecureBoot"
#!/bin/bash
if [[ -z "$1" ]]; then
echo "Usage: $0 module [module...]"
exit 1
fi
mydir=$(dirname $0)
PROMPT="${PROMPT:-Enter Machine Owner Key (MOK) passphrase: }"
KERNELVER=${KERNELVER:-$(uname -r)}
read_passphrase() {
# We write to /dev/tty to get around DKMS' redirection to /dev/null if it's being run with -q (e.g. during rpm installs)
echo -n "$PROMPT" > /dev/tty
read -s KBUILD_SIGN_PIN < /dev/tty
export KBUILD_SIGN_PIN
echo > /dev/tty
openssl rsa -check -noout -passin env:KBUILD_SIGN_PIN -in $mydir/MOK.priv > /dev/null 2>&1
}
do_sign() {
/lib/modules/$KERNELVER/build/scripts/sign-file sha256 $mydir/MOK.priv $mydir/MOK.der "$1"
}
while ! read_passphrase; do echo "Wrong passphrase, please try again."; done
for module in $@; do
echo "Signing module: $module"
module_basename=${module:0:-3}
module_suffix=${module: -3}
if [[ "$module_suffix" == ".xz" ]]; then
unxz $module
do_sign $module_basename
xz -f $module_basename
elif [[ "$module_suffix" == ".gz" ]]; then
gunzip $module
do_sign $module_basename
gzip -9f $module_basename
else
do_sign $module
fi
done
@atar-axis

This comment has been minimized.

Copy link

atar-axis commented Jan 2, 2019

perfect! I will use this gist at https://github.com/atar-axis/xpadneo thank you for the efforts!

@atar-axis

This comment has been minimized.

Copy link

atar-axis commented Jan 3, 2019

btw, how is this code licensed? :)

@ColMelvin

This comment has been minimized.

Copy link

ColMelvin commented Dec 2, 2019

I am using the following for my /etc/dkms/<module_name>.conf file, which removes the need for dkms-sign-module:

POST_BUILD="../../../../../../root/module-signing/sign-module ../$kernelver/$arch/module/*.ko*"

I made this change because I found dkms autoinstall provides neither $kernelver nor $arch to the dkms-sign-module script. Instead, I had to use dkms install <module>/<version> (or dkms build <module>/<version>) in order to get those values, making automation further up the stack more difficult.

The root cause can be found in the dkms binary and the problem is outlined below:

When running dkms build …, the script ends up calling maybe_build_module(), which sets the two variables ($kernelver & $arch), along with $module & $module_version, in a global scope before it calls build_module and, similarly, maybe_install_module sets the 4 variables before it calls install_module (which, itself, calls build_module as needed). This means that all 4 variables are available to the POST_BUILD script.

However, when autoinstall() calls install_module (and the implicit build_module, as needed), it only sets $module & $module_version in the global scope. For $kernelver & $arch, it relies on the already defined values, which were previously declared in a local scope; as such, they are not passed on to the POST_BUILD script.

@dop3j0e

This comment has been minimized.

Copy link
Owner Author

dop3j0e commented Dec 4, 2019

perfect! I will use this gist at https://github.com/atar-axis/xpadneo thank you for the efforts!

btw, how is this code licensed? :)

Glad it's finding some use :) It's WTFPL licensed, go do what you like ;)

@dop3j0e

This comment has been minimized.

Copy link
Owner Author

dop3j0e commented Dec 4, 2019

@ColMelvin So that's why that never worked right! I never took the time to get to the bottom of that, so thanks a lot for the investigation and elaborate writeup 👍
I'll try your approach on my work laptop soon, will update the gist after testing.

@Skirmisher

This comment has been minimized.

Copy link

Skirmisher commented Dec 7, 2019

@ColMelvin That information might be useful to mention on this issue I reported against dkms about a year ago. 😅

@ColMelvin

This comment has been minimized.

Copy link

ColMelvin commented Dec 7, 2019

@Skirmisher Thanks for letting me know about that; I was wondering where I should submit a bug report. Comment added, pretty much verbatim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.