Skip to content

Commit

Permalink
Merge pull request #816 from nasastry/kexec-secureboot
Browse files Browse the repository at this point in the history
testcases/OpTestKexec.py: add new test cases with -s and -c options
  • Loading branch information
PraveenPenguin authored Apr 23, 2024
2 parents 42b39e5 + ec1c45f commit e4c4fb6
Showing 1 changed file with 122 additions and 8 deletions.
130 changes: 122 additions & 8 deletions testcases/OpTestKexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
kexec, except for the kexec in loop test.
'''

import os
import unittest
import OpTestLogger

Expand All @@ -58,6 +59,7 @@

log = OpTestLogger.optest_logger_glob.get_logger(__name__)


class OpTestKexec(unittest.TestCase):
"""kexec test class"""

Expand All @@ -75,10 +77,8 @@ def populate_kernel_initrd_image(self):
and initrd_image instance variable
"""

distro = self.op_test_util.distro_name()

# Skip the test for unsupported distro
if distro == "unknown":
if self.distro == "unknown":
self.skipTest("Unsupported distro")

# Find kexec kernel version. If user provided the kernel source
Expand All @@ -99,13 +99,13 @@ def populate_kernel_initrd_image(self):
# Set kernel_image and initrd_image instance variable with
# corresponding filenames path
k_ver = str(k_ver)
if distro == "rhel":
if self.distro == "rhel":
self.kernel_image = "vmlinuz-" + k_ver
self.initrd_image = "initramfs-" + k_ver + ".img"
elif distro == "sles":
elif self.distro == "sles":
self.kernel_image = "vmlinux-" + k_ver
self.initrd_image = "initrd-" + k_ver
elif distro == "ubuntu":
elif self.distro == "ubuntu":
self.kernel_image = "vmlinux-" + k_ver
self.initrd_image = "initrd.img-" + k_ver

Expand All @@ -115,7 +115,7 @@ def setUp(self):
self.cv_SYSTEM = conf.system()
self.c = self.cv_SYSTEM.console
self.cv_HOST = conf.host()
self.distro = None
self.distro = self.op_test_util.distro_name()
self.num_of_iterations = conf.args.num_of_iterations
self.kernel_image = conf.args.kernel_image
self.initrd_image = conf.args.initrd_image
Expand All @@ -132,7 +132,7 @@ def setUp(self):
self.os_level_secureboot = sb_utilities.check_os_level_secureboot_state()

def get_kexec_load_cmd(self, load_opt=True, copy_cmdline=True,
file_load=False, add_arg=None):
syscall_load=False, file_load=False, add_arg=None):
"""
Generates a kexec command for loading a kernel image with various
optional arguments.
Expand All @@ -159,6 +159,9 @@ def get_kexec_load_cmd(self, load_opt=True, copy_cmdline=True,
if file_load:
kexec_cmd = kexec_cmd + " -s"

if syscall_load:
kexec_cmd = "%s -c" % kexec_cmd

if copy_cmdline:
kexec_cmd = kexec_cmd + " --append=\"`cat /proc/cmdline`\""

Expand Down Expand Up @@ -350,10 +353,59 @@ def test_load_and_exec(self):
ret = self.load_kexec_kernel(kexec_load_cmd)
self.assertTrue(ret, "Kexec load failed")

kexec_exec_cmd = self.get_kexec_exec_command(exec_opt=True)
ret = self.execute_kexec_cmd(kexec_exec_cmd, raw_pty_console=True)
self.assertTrue(ret, "kexec exec failed: %s " % kexec_exec_cmd)

def test_file_load_and_exec(self):
"""
Test kexec functionality by loading with kexec-file-syscall and exec
into kexec kernel.
First load the kexec kernel using -s, -l and --append(command line
arguments of currently running kenrel form /proc/cmdline) option.
Then exec into kexec kernel.
Test passes if both the kexec load and the execution into the
kexec kernel go fine; otherwise, it fails."
"""

kexec_load_cmd = self.get_kexec_load_cmd(file_load=True)
ret = self.load_kexec_kernel(kexec_load_cmd)
self.assertTrue(ret, "Kexec load failed")

kexec_exec_cmd = self.get_kexec_exec_command(exec_opt=True)
ret = self.execute_kexec_cmd(kexec_exec_cmd, raw_pty_console=True)
self.assertTrue(ret, "kexec exec failed: " + kexec_exec_cmd)

def test_syscall_load_and_exec(self):
"""
Test kexec functionality by loading with kexec-syscall and exec
into kexec kernel.
First load the kexec kernel using -c, -l and --append(command line
arguments of currently running kenrel form /proc/cmdline) option.
Then exec into kexec kernel.
Test passes if both the kexec load and the execution into the
kexec kernel go fine; otherwise, it fails."
"""

kexec_load_cmd = self.get_kexec_load_cmd(syscall_load=True)
ret = self.load_kexec_kernel(kexec_load_cmd)
if self.os_level_secureboot:
self.assertFalse(ret, "Kexec load pass, with -c option")
else:
self.assertTrue(ret, "Kexec load failed, with -c option")

kexec_exec_cmd = self.get_kexec_exec_command(exec_opt=True)
if self.os_level_secureboot:
ret = self.execute_kexec_cmd(kexec_exec_cmd)
self.assertFalse(ret, "Kexec exec pass, with -c option")
else:
ret = self.execute_kexec_cmd(kexec_exec_cmd, raw_pty_console=True)
self.assertTrue(ret, "Kexec exec failed, with -c option")

def test_kexec_force(self):
"""
Test kexec load and exec into kexec kernel using --force (-f) option.
Expand Down Expand Up @@ -397,6 +449,65 @@ def test_kexec_in_loop(self):
self.assertTrue(ret, "kexec failed, at iteration cnt: " + str(i))
log.info("Completed kexec iteration cnt %s." % str(i))

def test_kexec_unsigned_kernel(self):
"""
Tests the unsigned kernel when secure boot is enabled.
From the signed kernel image, create unsigned kernel image. The same
used for 'kexec' when secure boot is enabled. Expected failure while
loading kexec.
"""
if self.os_level_secureboot:
if self.op_test_util.check_kernel_signature():
if self.distro in ["unknown", "ubuntu"]:
self.skipTest("Unsupported Linux distribution.")
install_cmd = "wget"
wget_bool = True
res = self.cv_HOST.host_run_command('which %s' % install_cmd,
timeout=120)
if install_cmd not in res[0]:
wget_bool = False
if not wget_bool:
if self.distro == "rhel":
install_cmd = "yum install -y %s" % install_cmd
elif self.distro == "sles":
install_cmd = "zypper install -y %s" % install_cmd
self.cv_HOST.host_run_command(install_cmd, timeout=120)
try:
url = "https://raw.githubusercontent.com/torvalds/linux/master/scripts/extract-module-sig.pl"
self.cv_HOST.host_run_command("wget %s -P /tmp/" % url, timeout=120)
except CommandFailed:
self.skipTest("Can't get extract-module-sig.pl file.")
module_sig_file = '/tmp/extract-module-sig.pl'
self.cv_HOST.host_run_command("chmod u+x %s" % module_sig_file)
self.kernel_image = "/boot/%s" % self.kernel_image
cmd = "%s -0 %s > %s.unsigned" % \
(module_sig_file, self.kernel_image, self.kernel_image)
out = self.cv_HOST.host_run_command(cmd)
if '0' not in out[3]:
self.skipTest("Can not create unsigned binary. Using- %s"
% cmd)
cmd = "kexec -s -l %s.unsigned" % self.kernel_image
ret = self.execute_kexec_cmd(cmd)
if ret:
self.fail("kexec loaded unsigned kernel when secure boot"
" is enabled.")
else:
log.info("kexec loading with unsigned kernel failed. "
"Which is expected.")
else:
self.skipTest("secure boot is disabled.")

def tearDown(self):
unsigned_kernel = "%s.unsigned" % self.kernel_image
if 'boot' not in unsigned_kernel:
unsigned_kernel = "/boot/%s" % unsigned_kernel
if os.path.exists(unsigned_kernel):
os.remove(unsigned_kernel)
sign_file = "/tmp/extract-module-sig.pl"
if os.path.exists(sign_file):
os.remove(sign_file)


def kexec_suite():
"""kexec test suite"""
Expand All @@ -406,5 +517,8 @@ def kexec_suite():
suite.addTest(OpTestKexec('test_load_and_exec'))
suite.addTest(OpTestKexec('test_kexec_force'))
suite.addTest(OpTestKexec('test_kexec_single_step'))
suite.addTest(OpTestKexec('test_file_load_and_exec'))
suite.addTest(OpTestKexec('test_syscall_load_and_exec'))
suite.addTest(OpTestKexec('test_kexec_in_loop'))
suite.addTest(OpTestKexec('test_kexec_unsigned_kernel'))
return suite

0 comments on commit e4c4fb6

Please sign in to comment.