Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to verify reboot for secure boot #979

Merged
merged 14 commits into from
Jul 13, 2020
11 changes: 7 additions & 4 deletions scripts/fast-reboot
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ EXIT_SYNCD_SHUTDOWN=11
EXIT_FAST_REBOOT_DUMP_FAILURE=12
EXIT_FILTER_FDB_ENTRIES_FAILURE=13
EXIT_NO_CONTROL_PLANE_ASSISTANT=20
EXIT_SONIC_INSTALLER_VERIFY_REBOOT=21

function error()
{
Expand Down Expand Up @@ -305,10 +306,12 @@ function reboot_pre_check()
exit ${EXIT_FILE_SYSTEM_FULL}
fi

# Make sure that the next image exists
if [[ ! -d ${IMAGE_PATH} ]]; then
debug "Next image ${NEXT_SONIC_IMAGE} doesn't exist ..."
exit ${EXIT_NEXT_IMAGE_NOT_EXISTS}
# Verify the next image by sonic_installer
INSTALLER_VERIFY_RC=0
sonic_installer verify-next-image > /dev/null || INSTALLER_VERIFY_RC=$?
if [[ INSTALLER_VERIFY_RC -ne 0 ]]; then
error "Failed to verify next image. Exit code: $INSTALLER_VERIFY_RC"
exit ${EXIT_SONIC_INSTALLER_VERIFY_REBOOT}
fi

# Make sure ASIC configuration has not changed between images
Expand Down
10 changes: 6 additions & 4 deletions scripts/reboot
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ PLAT_REBOOT="platform_reboot"
REBOOT_CAUSE_FILE="/host/reboot-cause/reboot-cause.txt"
VERBOSE=no
EXIT_NEXT_IMAGE_NOT_EXISTS=4
EXIT_SONIC_INSTALLER_VERIFY_REBOOT=21

function debug()
{
Expand Down Expand Up @@ -79,10 +80,11 @@ function reboot_pre_check()
fi
rm ${filename}

# Make sure that the next image exists
if [[ ! -d ${IMAGE_PATH} ]]; then
VERBOSE=yes debug "Next image ${NEXT_SONIC_IMAGE} doesn't exist ..."
exit ${EXIT_NEXT_IMAGE_NOT_EXISTS}
# Verify the next image by sonic_installer
local message=$(sonic_installer verify-next-image 2>&1)
if [ $? -ne 0 ]; then
VERBOSE=yes debug "Failed to verify next image: ${message}"
exit ${EXIT_SONIC_INSTALLER_VERIFY_REBOOT}
fi
}

Expand Down
12 changes: 10 additions & 2 deletions sonic_installer/bootloader/aboot.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .bootloader import Bootloader

_secureboot = None
DEFAULT_SWI_IMAGE = 'sonic.swi'

# For the signature format, see: https://github.com/aristanetworks/swi-tools/tree/master/switools
SWI_SIG_FILE_NAME = 'swi-signature'
Expand Down Expand Up @@ -110,9 +111,9 @@ def remove_image(self, image):
self._boot_config_set(SWI=image_path, SWI_DEFAULT=image_path)
click.echo("Set next and default boot to current image %s" % current)

image_dir = image.replace(IMAGE_PREFIX, IMAGE_DIR_PREFIX)
image_path = self.get_image_path(image)
click.echo('Removing image root filesystem...')
subprocess.call(['rm','-rf', os.path.join(HOST_PATH, image_dir)])
subprocess.call(['rm','-rf', image_path])
click.echo('Image removed')

def get_binary_image_version(self, image_path):
Expand All @@ -129,6 +130,13 @@ def verify_binary_image(self, image_path):
except subprocess.CalledProcessError:
return False

def verify_next_image(self):
if not super(AbootBootloader, self).verify_next_image():
return False
image = self.get_next_image()
image_path = os.path.join(self.get_image_path(image), DEFAULT_SWI_IMAGE)
return self._verify_secureboot_image(image_path)

def _verify_secureboot_image(self, image_path):
if isSecureboot():
cert = self.getCert(image_path)
Expand Down
20 changes: 20 additions & 0 deletions sonic_installer/bootloader/bootloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
Abstract Bootloader class
"""

from os import path

from ..common import (
HOST_PATH,
IMAGE_DIR_PREFIX,
IMAGE_PREFIX,
)

class Bootloader(object):

NAME = None
Expand Down Expand Up @@ -43,8 +51,20 @@ def verify_binary_image(self, image_path):
"""verify that the image is supported by the bootloader"""
raise NotImplementedError

def verify_next_image(self):
"""verify the next image for reboot"""
image = self.get_next_image()
jleveque marked this conversation as resolved.
Show resolved Hide resolved
image_path = self.get_image_path(image)
return path.exists(image_path)

@classmethod
def detect(cls):
"""returns True if the bootloader is in use"""
return False

@classmethod
def get_image_path(cls, image):
"""returns the image path"""
prefix = path.join(HOST_PATH, IMAGE_DIR_PREFIX)
return image.replace(IMAGE_PREFIX, prefix)

10 changes: 10 additions & 0 deletions sonic_installer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,5 +476,15 @@ def rollback_docker(container_name):

click.echo('Done')

# verify the next image
@cli.command('verify-next-image')
def verify_next_image():
""" Verify the next image for reboot"""
bootloader = get_bootloader()
if not bootloader.verify_next_image():
click.echo('Image verification failed')
sys.exit(1)
click.echo('Image successfully verified')

if __name__ == '__main__':
cli()