Skip to content

Instantly share code, notes, and snippets.

@amaksoft
Last active March 21, 2024 05:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amaksoft/2495d0bf4df406793b5082ebb6d4aa4d to your computer and use it in GitHub Desktop.
Save amaksoft/2495d0bf4df406793b5082ebb6d4aa4d to your computer and use it in GitHub Desktop.
Virtualbox and VMware modules signing for Fedora
#!/bin/bash
#
# Inspired by:
# http://gorka.eguileor.com/vbox-vmware-in-secureboot-linux-2016-update/
# http://elemc.name/?p=1020
#
# Designed and tested on Fedora 24/25
#
# This script is designed to automate Virtualbox and VMware module signing for SecureBoot
# Run it after each "vmware-modconfig --console --install-all", "/sbin/rcvboxdrv setup", "sudo /etc/init.d/vboxdrv setup" or kernel update
#
# Step 1. Generate a certificate:
#
# $ sudo mkdir /etc/pki/my-secureboot
# $ cd /etc/pki/my-secureboot
# $ sudo openssl req -new -x509 -newkey rsa:4096 -keyout private_key.priv -outform DER -out public_key.der -nodes -days 36500 -subj "/CN=MySecureBoot/"
#
# Or use Fedora manual https://docs.fedoraproject.org/en-US/Fedora/25/html/System_Administrators_Guide/sect-generating-a-public-private-x509-key-pair.html
#
# Step 2. Install certificate:
#
# $ sudo mokutil --import public_key.der
#
# Step 3a. Reboot after installing certificate and enter the password you set in previous step
#
# $ sudo reboot
#
# Step 3b. Check if certificates are loaded
#
# $ dmesg | grep 'EFI: Loaded cert'
#
# Step 4. Get and run this script
#
# $ sudo wget https://gist.github.com/amaksoft/2495d0bf4df406793b5082ebb6d4aa4d/raw/f6b8ae4a8257ca721e263e68741e5df516309b66/70-sign-virtual.sh
# $ sudo chmod +x 70-sign-virtual.sh
# $ sudo ./70-sign-virtual.sh
#
# Step 5. Add to kernel postinstall scripts
#
# $ sudo mv 70-sign-virtual.sh /etc/kernel/postinst.d/
########################### Settings #############################
# Signing keys names (change if you name your keys differently)
KEYS="private_key.priv public_key.der"
# Signing keys location (change if you put your keys in different directory)
KEYS_DIR="/etc/pki/my-secureboot"
# Kernel modules names to check
# (We will sign every module located in the same directory with those)
MOD_NAMES="vboxdrv vmmon vmnet"
# Services to restart after signing modules
SERVICES="vboxdrv vmware"
############################# Code ##############################
ERROR_PREFIX="ERROR ($BASH_SOURCE:$LINENO)"
error () {
printf "\e[31m$ERROR_PREFIX\e[0m $2\n"
exit $1
}
# Check if running as root (for manual run)
if [ "$EUID" -ne 0 ]; then
error 1 "Please run this script as root!";
fi
# Get script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";
KCUR=$(uname -r) # Current kernel version
if [[ $SCRIPT_DIR == "/etc/kernel/postinst.d" ]] && [[ ! -z "${1// }" ]]; then
KINST=$1
KVER=$KINST
echo "Running as postinstall script for kernel $KVER"
else
KVER=$KCUR
echo "Running manually for kernel $KVER"
fi
# Use script directory for keys if declared keys directory doesn't exist (for manual run)
if [ -d $KEYS_DIR ]; then
DIR=$KEYS_DIR
else
DIR=$SCRIPT_DIR
fi
# Append directory to keys names
for k in $KEYS; do
KEYS_+="$DIR/$k "
done
KEYS=$KEYS_
# Check if keys exist
for f in $KEYS; do
if [ ! -f $f ]; then
error 2 "$(basename $f) not found! \n Please generate keys and copy them in $KEYS_DIR or $SCRIPT_DIR.";
fi
done
# Get modules locations
for m in $MOD_NAMES; do
if modinfo -n $m > /dev/null 2>&1; then
M_DIR=$(dirname $(modinfo -n $m))
if [[ $KCUR != $KVER ]]; then
M_DIR=${M_DIR/$KCUR/$KVER}
fi
for d in $MODULE_DIRS; do
if [[ $d == $M_DIR ]]; then
M_DIR=""
break
fi
done
MODULE_DIRS+="$M_DIR "
fi
done
if [[ -z "${MODULE_DIRS// }" ]]; then
error 3 "no modules found. Checked [$MOD_NAMES]";
fi
# Sign modules
MOD_TO_SIGN=$(find $MODULE_DIRS -name '*.ko')
if [[ -z "${MOD_TO_SIGN// }" ]]; then
error 4 "no modules found in dirs $MODULE_DIRS";
fi
for f in $MOD_TO_SIGN; do
echo "Signing $f";
/usr/src/kernels/$KVER/scripts/sign-file sha256 $KEYS $f;
done
# Restart services
for serv in $SERVICES; do
MSG="Restart $serv service"
# check if service exists
if systemctl -t service -a | grep -Fq $serv; then
if systemctl restart $serv; then
echo "$MSG successful";
else
error 5 "$MSG failed";
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment