Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Signing VirtualBox Kernel Modules

Signing VirtualBox Kernel Modules

These are the steps I followed enable VirtualBox on my laptop without disabling UEFI Secure Boot. They're nearly identical to the process described on Øyvind Stegard's blog, save for a few key details. The images here are borrowed from the Systemtap UEFI Secure Boot Wiki.

  1. Install the VirtualBox package (this might be different for your platform).

    src='https://download.virtualbox.org/virtualbox/rpm/fedora/virtualbox.repo'
    dst='/etc/yum.repos.d/virtualbox.repo'
    sudo curl ${src} > ${dst}
    dnf check-update
    sudo dnf install VirtualBox-6.0
  2. Create an RSA key pair to sign kernel modules.

    name="$(getent passwd $(whoami) | awk -F: '{print $5}')"
    out_dir='/root/module-signing'
    sudo mkdir ${out_dir}
    sudo openssl \
        req \
        -new \
        -x509 \
        -newkey \
        rsa:2048 \
        -keyout ${out_dir}/MOK.priv \
        -outform DER \
        -out ${out_dir}/MOK.der \
        -days 36500 \  # This is probably waaay too long.
        -subj "/CN=${name}/"
    sudo chmod 600 ${out_dir}/MOK*

    Note the absence of the -nodes option from Øyvind's post. With this option openssl will create a private key with no passphrase. The omission of this option prompts for a passphrase, which seems like a good idea for something as important as a kernel module signing key.

  3. Import the MOK ("Machine Owner Key") so it can be trusted by the system.

    sudo mokutil --import /root/module-signing/MOK.der

    This will prompt for a password. The password is only temporary and will be used on the next boot. It does not have to be the same as the signing key passphrase.

  4. Reboot your machine to enter the MOK manager EFI utility.

    • Select Enroll MOK.

    Enroll MOK

    • Select Continue.

    Continue

    • Select Yes to enroll the keys.

    Confirm

    • Enter the password from earlier.

    Enter password

    • Select OK to reboot.

    Reboot

    • Verify the key has been loaded by finding the it in the output of
    dmesg | grep '[U]EFI.*cert'
  5. Create a script for signing all the VirtualBox kernel modules.

    #!/bin/sh
    
    readonly hash_algo='sha256'
    readonly key='/root/module-signing/MOK.priv'
    readonly x509='/root/module-signing/MOK.der'
    
    readonly name="$(basename $0)"
    readonly esc='\\e'
    readonly reset="${esc}[0m"
    
    green() { local string="${1}"; echo "${esc}[32m${string}${reset}"; }
    blue() { local string="${1}"; echo "${esc}[34m${string}${reset}"; }
    log() { local string="${1}"; echo "[$(blue $name)] ${string}"; }
    
    # The exact location of `sign-file` might vary depending on your platform.
    alias sign-file="/usr/src/kernels/$(uname -r)/scripts/sign-file"
    
    [ -z "${KBUILD_SIGN_PIN}" ] && read -p "Passphrase for ${key}: " KBUILD_SIGN_PIN
    export KBUILD_SIGN_PIN
    
    for module in $(dirname $(modinfo -n vboxdrv))/*.ko; do
      log "Signing $(green ${module})..."
      sign-file "${hash_algo}" "${key}" "${x509}" "${module}"
    done

    This script differs from Øyvind's in two aspects. First, and most importantly, it has C O L O R S . Second, it uses the magic $KBUILD_SIGN_PIN environment variable that doesn't appear anywhere in the sign-file usage. I went spelunking in the Linux source for it, but in hindsight I could have just read the docs on manual module signing... I wrote this script to /root/bin/sign-vbox-modules as that's usually on root's $PATH.

  6. Execute the aforementioned script as root.

    sudo chmod 700 /root/bin/sign-vbox-modules
    sudo -i sign-vbox-modules
  7. Load the vboxdrv module.

    sudo modprobe vboxdrv
@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Feb 11, 2019

Aftermath

So, this didn't work as well as I would have liked for some reason... In attempting to sign these kernel modules again after a kernel update I hosed my system by corrupting my initramfs. Essentially, be careful. There be dragons here. 🐲

I ended up just disabling UEFI Secure Boot anyway. 🙃

@reinderien

This comment has been minimized.

Copy link

reinderien commented Jun 4, 2019

This doesn't work at all for me, unfortunately. sign-file is in the wrong place:

~$ find /usr/src -name sign-file
/usr/src/linux-headers-4.15.0-50-generic/scripts/sign-file
@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Jun 5, 2019

@reinderien:

This doesn't work at all

seems uncharitable to me as I mentioned in the comment that

# The exact location of `sign-file` might vary depending on your platform.

I wrote this guide on Fedora, where it did work, but a different distro might place those files elsewhere as you said.

@reinderien

This comment has been minimized.

Copy link

reinderien commented Jun 6, 2019

@agabopinho

This comment has been minimized.

Copy link

agabopinho commented Jun 29, 2019

Everything worked perfectly. Thank you!

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Jun 29, 2019

Glad this helped you, @agabopinho! 😄

@RJColeman

This comment has been minimized.

Copy link

RJColeman commented Jul 28, 2019

I had to add this to the signing script:
export KBUILD_SIGN_PIN
Worked like a charm after that. Thank you so much for this!

@brasey

This comment has been minimized.

Copy link

brasey commented Aug 9, 2019

I had to add this to the signing script:
export KBUILD_SIGN_PIN
Worked like a charm after that. Thank you so much for this!

Yup, this worked for me too, thanks!

@noelalanguilan

This comment has been minimized.

Copy link

noelalanguilan commented Aug 21, 2019

I had to add this to the signing script:
export KBUILD_SIGN_PIN
Worked like a charm after that. Thank you so much for this!

Where did you put it in the script? I am new and just reading up about this before diving in.

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Aug 21, 2019

@noelalanguilan: The best spot to add that is probably immediately after its definition

[ -z "${KBUILD_SIGN_PIN}" ] && read -p "Passphrase for ${key}: " KBUILD_SIGN_PIN

like

[ -z "${KBUILD_SIGN_PIN}" ] && read -p "Passphrase for ${key}: " KBUILD_SIGN_PIN
export KBUILD_SIGN_PIN

This is actually a mistake on my part and I'll correct it in the Gist. I had KBUILD_SIGN_PIN already defined in my environment, so the first part of the expression short circuits the call to read and the environment variable passes right on through to sign-file.

In the case of these other folks though, they probably didn't have it defined in the parent environment, so when read prompts for it it's defined within that scope, but not exported so that sign-file can access it. Basically, it's necessary to export when prompted for and won't hurt if it's already defined.

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Aug 21, 2019

The absent

export KBUILD_SIGN_PIN

has been included in the Gist now. Thanks, @RJColeman.

@mikfra

This comment has been minimized.

Copy link

mikfra commented Aug 22, 2019

Using Fedora30:Kern-5.2.9 I had to take additional steps to compile the vbox kernel modules.

mv /usr/share/virtualbox/src/vboxhost/* /lib/modules/5.2.9-200.fc30.x86_64/misc/
make && make install
/root/bin/sign-vbox.sh

modified line for module in $(dirname $(modinfo -n vboxdrv))/.k to for module in $(dirname $(modinfo -n vbox*))/.k

modprobe vboxdrv

*Was able to boot a VM after modprobe vboxdrv

  • Ran into errors for the other Vboxpci modules. Assuming my Motherboard may not have IOMMU or vt-d support. Not to familiar with Virtual Box. Spoiled with VMware all my life lol
    Cheers, Hope this helps!
@raul1991

This comment has been minimized.

Copy link

raul1991 commented Oct 16, 2019

PKCS#7 signature not signed with a trusted key

I am getting this error after running the script.

@hoxsiew

This comment has been minimized.

Copy link

hoxsiew commented Oct 31, 2019

Could you elaborate some on step 4? I don't get a "MOK manager EFI utility" upon reboot, just a normal bootup.

@raul1991

This comment has been minimized.

Copy link

raul1991 commented Nov 1, 2019

I re-imported the MOK and it worked fine.

@hoxsiew

This comment has been minimized.

Copy link

hoxsiew commented Nov 1, 2019

I tried that before and got a message that the MOK was already in the enrollment request.

@Jerczey

This comment has been minimized.

Copy link

Jerczey commented Nov 14, 2019

well u rock, here's a star or whatever is a 'Like' on this :)

@chipmunk03

This comment has been minimized.

Copy link

chipmunk03 commented Nov 27, 2019

Hi Reillysiemens,

thanks for this helpful script. I adjusted it a little for my distribution (elementary), which is a Debian/Ubuntu based GNU Linux distro. I want to share it with you, so it might work on other distributions as well.

Add above this line in reillysiemens script
[ -z "${KBUILD_SIGN_PIN}" ] && read -p "Passphrase for ${key}: " KBUILD_SIGN_PIN

this piece of code:

# source /etc/os-release
. /etc/os-release

# The exact location of sign-file" might vary depending on your platform.

case ${ID_LIKE} in
       "rhel centos") alias sign-file="/usr/src/kernel/$(uname -r)/scripts/sign-file"
                ;;
        "debian" | "ubuntu") alias sign-file="/usr/src/linux-headers-$(uname -r)/scripts/sign-file"
                ;;
#       "ubuntu") alias sign-file="/usr/src/linux-headers-$(uname -r)/scripts/sign-file"
#               ;;
        *) echo "Unknown distribution"
           exit 99
esac

If you have only one kernel version installed, you can use the find method like this
alias sign-file="$(find /usr/src -name sign-file)"
I have more than one kernel versions installed, so this does not work for me. I use the 'case' construct instead.

Cheers.

@cierzniak

This comment has been minimized.

Copy link

cierzniak commented Dec 1, 2019

Debian 10.2 (kernel from backports)

$ dpkg -S sign-file
linux-kbuild-5.3: /usr/lib/linux-kbuild-5.3/scripts/sign-file
linux-kbuild-4.19: /usr/lib/linux-kbuild-4.19/scripts/sign-file
$ sudo find /usr/src -name sign-file
$ sudo find /usr/lib -name sign-file
/usr/lib/linux-kbuild-4.19/scripts/sign-file
/usr/lib/linux-kbuild-5.3/scripts/sign-file
@Prashy27

This comment has been minimized.

Copy link

Prashy27 commented Dec 19, 2019

A very useful article! Steps were very clear and informative.

@AlekseyPn

This comment has been minimized.

Copy link

AlekseyPn commented Dec 19, 2019

Thanks!!! I finally victory!!! :D

@alexhanssens

This comment has been minimized.

Copy link

alexhanssens commented Jan 1, 2020

after entering the first command under 2:
name="$(getent passwd $(whoami) | awk -F: '{print $5}')"
I get " Illegal variable name"
I do something wrong?

@m4ldonado

This comment has been minimized.

Copy link

m4ldonado commented Jan 2, 2020

Thanks!

The MOK manager EFI utility didn't load for me on Fedora 31 because the shim had lower boot priority. Solution:

  1. copy the boot order from efibootmgr -v putting the number of the shim first
  2. efibootmgr -o [boot order you copied]
@4levels

This comment has been minimized.

Copy link

4levels commented Jan 28, 2020

You saved my life many times (again just now) with this gist, after every major OS update on Debian I keep coming back to this!

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Jan 31, 2020

@alexhanssens: If you're not using a Bash-like shell, for example csh or tcsh, then you might encounter an error like that. If that's the case, then you might have better luck with something like

setenv name `getent passwd $USER | awk -F: '{print $5}'`
@RailRunner166

This comment has been minimized.

Copy link

RailRunner166 commented Feb 6, 2020

hey all, hopefully you can offer some assistance on an issue ive been having.
I have reached step three and have imported the mok, however when i restart my computer (i'm running arch just in case this is an arch thing) it doesn't show the blue screen...
Any ideas?

Thanks

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Feb 8, 2020

@RailRunner166: I don't run Arch myself, so I've no immediate suggestions, but the Arch Wiki page on Secure Boot seems pretty detailed. Interestingly I couldn't find mention of mokutil anywhere on that page, so maybe they recommend a different approach.

@reillysiemens

This comment has been minimized.

Copy link
Owner Author

reillysiemens commented Feb 10, 2020

@RailRunner166: Thinking about it a little more, maybe @m4ldonado's comment has something to do with your troubles. Might be worth looking into that angle.

@RailRunner166

This comment has been minimized.

Copy link

RailRunner166 commented Feb 11, 2020

Eh, it turned out I didn't even need to sign my modules at all 😆 (secure boot was off) so uh, thanks anyway 😄

@ChrisRoald

This comment has been minimized.

Copy link

ChrisRoald commented Mar 14, 2020

Hi,
After reinstalling the virtualbox module virtualbox-dkms using synaptic, I get a dialog that asks me to enter and verify a pass-key that'll be used in MOK management when I reboot. But MOK Management isn't listed in my reboot screen; nor does it appear automatically. Is there something additional I need to do, either in or after the synaptic module reinstall, to get MOK working at reboot?
Thanks

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.