Skip to content

Commit

Permalink
Support for unified kernels and signing them
Browse files Browse the repository at this point in the history
  • Loading branch information
jackpot51 committed Aug 28, 2022
1 parent 41819bb commit bc4a75e
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 21 deletions.
48 changes: 32 additions & 16 deletions kernelstub/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ def main(self, args): # Do the thing
' ESP Location:..................%s\n' % configuration['esp_path'] +
' Management Mode:...............%s\n' % configuration['manage_mode'] +
' Install Loader configuration:..%s\n' % configuration['setup_loader'] +
' Unified kernel:................%s\n' % configuration['unified_kernel'] +
' Configuration version:.........%s\n' % configuration['config_rev'])
log.info('Configuration details: \n\n%s' % all_config)
exit(0)
Expand All @@ -325,25 +326,40 @@ def main(self, args): # Do the thing
kopts = 'root=UUID=%s ro %s' % (drive.root_uuid, " ".join(kernel_opts))
log.debug('kopts: %s' % kopts)



installer.setup_kernel(
kopts,
setup_loader=setup_loader,
overwrite=force,
simulate=no_run)
try:
installer.backup_old(
if configuration['unified_kernel']:
installer.setup_unified_kernel(
kopts,
old=False,
simulate=no_run
)
try:
installer.setup_unified_kernel(
kopts,
old=True,
simulate=no_run)
except Exception as e:
log.debug('Couldn\'t back up old kernel. \nThis might just mean ' +
'You don\'t have an old kernel installed. If you do, try ' +
'with -vv to see debuging information')
log.debug(e)
else:
installer.setup_kernel(
kopts,
setup_loader=setup_loader,
overwrite=force,
simulate=no_run)
except Exception as e:
log.debug('Couldn\'t back up old kernel. \nThis might just mean ' +
'You don\'t have an old kernel installed. If you do, try ' +
'with -vv to see debuging information')
log.debug(e)

installer.copy_cmdline(simulate=no_run)
try:
installer.backup_old(
kopts,
setup_loader=setup_loader,
simulate=no_run)
except Exception as e:
log.debug('Couldn\'t back up old kernel. \nThis might just mean ' +
'You don\'t have an old kernel installed. If you do, try ' +
'with -vv to see debuging information')
log.debug(e)

installer.copy_cmdline(simulate=no_run)

if not manage_mode:
installer.setup_stub(kopts, simulate=no_run)
Expand Down
12 changes: 8 additions & 4 deletions kernelstub/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class Config():
'manage_mode': False,
'force_update' : False,
'live_mode' : False,
'config_rev' : 3
'unified_kernel': False,
'config_rev' : 4
}
}

Expand Down Expand Up @@ -107,7 +108,7 @@ def save_config(self, path='/etc/kernelstub/configuration'):

with open(path, mode='w') as config_file:
json.dump(self.config, config_file, indent=2)

self.log.debug('Configuration saved!')
return 0

Expand All @@ -120,8 +121,11 @@ def update_config(self, config):
config['user']['kernel_options'] = self.parse_options(config['user']['kernel_options'].split())
if type(config['default']['kernel_options']) is str:
config['default']['kernel_options'] = self.parse_options(config['default']['kernel_options'].split())
config['user']['config_rev'] = 3
config['default']['config_rev'] = 3
if config['user']['config_rev'] < 4:
config['user']['unified_kernel'] = False
config['default']['unified_kernel'] = False
config['user']['config_rev'] = 4
config['default']['config_rev'] = 4
return config

def parse_options(self, options):
Expand Down
67 changes: 66 additions & 1 deletion kernelstub/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
terms.
"""

import os, shutil, logging, platform, gzip
import os, shutil, logging, platform, gzip, subprocess

from pathlib import Path

Expand Down Expand Up @@ -58,6 +58,71 @@ def __init__(self, nvram, opsys, drive):
if not os.path.exists(self.entry_dir):
os.makedirs(self.entry_dir)

def setup_unified_kernel(self, kernel_opts, old=False, simulate=False):
if old:
suffix = 'previous'
kernel_path = self.opsys.old_kernel_path
initrd_path = self.opsys.old_initrd_path
else:
suffix = 'current'
kernel_path = self.opsys.kernel_path
initrd_path = self.opsys.initrd_path

tmp_dir = os.path.join('/tmp/kernelstub', suffix)
self.ensure_dir(tmp_dir, simulate=simulate)

cmdline_path = os.path.join(tmp_dir, 'cmdline')
if simulate:
self.log.info('Simulate creating file: %s with contents %s' % (cmdline_path, kernel_opts))
else:
with open(cmdline_path, mode='w') as f:
f.write(kernel_opts)

self.log.info('Creating unified Linux EFI executable (%s)' % (suffix))
kernel_unsigned_efi_path = os.path.join(tmp_dir, 'linux-unsigned.efi')
objcopy = [
'objcopy',
'--add-section', '.osrel=/usr/lib/os-release', '--change-section-vma', '.osrel=0x20000',
'--add-section', '.cmdline=' + cmdline_path, '--change-section-vma', '.cmdline=0x30000',
'--add-section', '.linux=' + kernel_path, '--change-section-vma', '.linux=0x2000000',
'--add-section', '.initrd=' + initrd_path, '--change-section-vma', '.initrd=0x3000000',
'/usr/lib/systemd/boot/efi/linuxx64.efi.stub', kernel_unsigned_efi_path
]
if simulate:
self.log.info('Simulate running command: %s' % (objcopy))
else:
subprocess.check_call(objcopy)

sign_crt = '/etc/kernelstub/db.crt'
sign_key = '/etc/kernelstub/db.key'
if os.path.exists(sign_crt) and os.path.exists(sign_key):
self.log.info('Signing unified Linux EFI executable (%s)' % (suffix))
kernel_signed_efi_path = os.path.join(tmp_dir, 'signed.efi')
sbsign = [
'sbsign',
'--cert', sign_crt,
'--key', sign_key,
'--output', kernel_signed_efi_path,
kernel_unsigned_efi_path
]
if simulate:
self.log.info('Simulate running command: %s' % (sbsign))
else:
subprocess.check_call(sbsign)
kernel_efi_path = kernel_signed_efi_path
else:
kernel_efi_path = kernel_unsigned_efi_path

self.log.info('Copying unified Linux EFI executable to ESP (%s)' % (suffix))
kernel_efi_dest_dir = os.path.join(self.work_dir, 'Linux')
self.ensure_dir(kernel_efi_dest_dir, simulate=simulate)
kernel_efi_name = self.opsys.name + '-' + suffix + '-' + self.drive.root_uuid + '.efi'
kernel_efi_dest = os.path.join(kernel_efi_dest_dir, kernel_efi_name)
self.copy_files(
kernel_efi_path,
kernel_efi_dest,
simulate=simulate
)

def backup_old(self, kernel_opts, setup_loader=False, simulate=False):
self.log.info('Backing up old kernel')
Expand Down

0 comments on commit bc4a75e

Please sign in to comment.