Skip to content

Instantly share code, notes, and snippets.

@chronos-tachyon
Last active July 1, 2022 22:06
Show Gist options
  • Save chronos-tachyon/cfd312e9d0986890fcaa3da3ba0cb3b7 to your computer and use it in GitHub Desktop.
Save chronos-tachyon/cfd312e9d0986890fcaa3da3ba0cb3b7 to your computer and use it in GitHub Desktop.
Python script for automatically running vmware-modconfig and signing the result for UEFI SecureBoot.
#!/usr/bin/env python3
import argparse
import os
import subprocess
import sys
from pathlib import Path
MOK_DIR = Path('/var/lib/shim-signed/mok')
MOK_DER = MOK_DIR / 'MOK.der'
MOK_PRIV = MOK_DIR / 'MOK.priv'
MAGIC = b'~Module signature appended~\n'
MAGIC_SIZE = len(MAGIC)
MODULE_NAMES = ['vmmon', 'vmnet']
def is_secureboot_enabled():
p = subprocess.run(['mokutil', '--sb-state'], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)
return (p.returncode == 0 and p.stdout == b'SecureBoot enabled\n')
def run(argv, check=True):
argv = list(map(str, argv))
print(f'+ {argv!r}', file=sys.stderr)
p = subprocess.run(argv)
print(f'+ rc={p.returncode}', file=sys.stderr)
if p.returncode == 0:
return True
elif check:
sys.exit(1)
else:
return False
def main(args):
os.environ.pop('DISPLAY', None)
for key in os.environ:
if key.startswith('LC_'):
del os.environ[key]
os.environ['PATH'] = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
os.environ['TZ'] = 'America/Los_Angeles'
os.environ['LANG'] = 'en_US.UTF-8'
os.umask(0o022)
HAS_MOK = MOK_PRIV.exists()
IS_SECUREBOOT = is_secureboot_enabled()
uname = os.uname()
KERNEL_VERSION = uname.release
SIGN_SCRIPT = Path(f'/usr/src/linux-headers-{KERNEL_VERSION}/scripts/sign-file')
MODULE_ROOT = Path(f'/lib/modules/{KERNEL_VERSION}')
MODULE_MISC = MODULE_ROOT / 'misc'
MODULE_FILENAMES = [name + '.ko' for name in MODULE_NAMES]
MODULE_FILES = [MODULE_MISC / filename for filename in MODULE_FILENAMES]
if args.force_sign and not HAS_MOK:
print('MOK does not exist, --force-sign will not work.')
print('You will need to run update-secureboot-policy to create and enroll a MOK.')
sys.exit(1)
need_build = args.force or args.force_build
need_sign = args.force or args.force_sign
for module_file in MODULE_FILES:
if not module_file.exists():
print(f'module {module_file} does not exist yet', file=sys.stderr)
need_build = True
need_sign = True
continue
if HAS_MOK:
with open(module_file, 'rb', buffering=0) as fp:
fp.seek(-MAGIC_SIZE, os.SEEK_END)
magic = fp.read(MAGIC_SIZE)
if magic != MAGIC:
print(f'module {module_file} is not signed yet', file=sys.stderr)
need_sign = True
continue
if need_build:
if not run(['vmware-modconfig', '--console', '--install-all'], check=False):
if IS_SECUREBOOT:
print('It\'s normal for vmware-modconfig to fail when SecureBoot is enabled.')
else:
sys.exit(1)
if HAS_MOK and need_sign:
for module_file in MODULE_FILES:
run([SIGN_SCRIPT, 'sha256', MOK_PRIV, MOK_DER, module_file])
if need_build or need_sign or args.force:
run(['update-initramfs', '-k', KERNEL_VERSION, '-c'])
run(['update-grub'])
if IS_SECUREBOOT:
print('You will probably need to reboot before you can run VMWare.')
print('If you have tried rebooting, verify that your MOK is enrolled.')
else:
print('If you are running this script manually, you may also need to run:\n'
'\tsystemctl restart vmware')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-f', '--force', action='store_true')
parser.add_argument('-S', '--force-sign', action='store_true')
parser.add_argument('-B', '--force-build', action='store_true')
main(parser.parse_args())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment