Needs Fixing: [PATCH autotest-client-tests] UBUNTU: SAUCE: ubuntu_boot: implement revocation list checks

Sean Feole sean.feole at canonical.com
Thu Jul 29 01:39:31 UTC 2021


This feature looks like a great addition, however, giving how critical 
the ubuntu_boot a-c-t is (This test is now a gate for initial kernel 
builds), we need to be careful how we update it.

Upon testing this patch against a test harness using Focal amd64 vm:


01:08:17 INFO | START ubuntu_boot.kernel_revocation_list 
ubuntu_boot.kernel_revocation_list timestamp=1627520897 timeout=300 
localtime=Jul 29 01:08:17 01:08:17 DEBUG| Persistent state 
client._record_indent now set to 2 01:08:17 DEBUG| Persistent state 
client.unexpected_reboot now set to 
('ubuntu_boot.kernel_revocation_list', 
'ubuntu_boot.kernel_revocation_list') 01:08:17 DEBUG| Waiting for pid 
2357 for 300 seconds 01:08:17 WARNI| System python is too old, crash 
handling disabled 01:08:17 ERROR| Exception escaping from test: 
Traceback (most recent call last): File 
"/home/ubuntu/autotest/client/shared/test.py", line 411, in _exec 
_call_test_function(self.execute, *p_args, **p_dargs) File 
"/home/ubuntu/autotest/client/shared/test.py", line 830, in 
_call_test_function raise error.UnhandledTestFail(e) UnhandledTestFail: 
Unhandled AttributeError: 'tuple' object has no attribute 'release' 
Traceback (most recent call last): File 
"/home/ubuntu/autotest/client/shared/test.py", line 823, in 
_call_test_function return func(*args, **dargs) File 
"/home/ubuntu/autotest/client/shared/test.py", line 291, in execute 
postprocess_profiled_run, args, dargs) File 
"/home/ubuntu/autotest/client/shared/test.py", line 212, in 
_call_run_once self.run_once(*args, **dargs) File 
"/home/ubuntu/autotest/client/tests/ubuntu_boot/ubuntu_boot.py", line 
97, in run_once self.kernel_revocation_list() File 
"/home/ubuntu/autotest/client/tests/ubuntu_boot/ubuntu_boot.py", line 
60, in kernel_revocation_list config_file = "/boot/config-" + 
os.uname().release AttributeError: 'tuple' object has no attribute 'release'

Full output here: https://pastebin.canonical.com/p/Zr2jjzsNcr/

Unfortunately autotest only supports python2, which is why this dumped 
an Exception, there is no os.uname().release. I think the best way to 
handle this:

1.) Re-write it all for python2 (no one wants to do that)

2.) Isolate the function into it's own py3 script and call it from 
ubuntu_boot.py using something like, utils.system('python3 
<my_python3_script>' ).

This is probably the easiest, any errors that are returned from the 
python3 script can be handled in "ubuntu_boot.py" using the 
autotest.client library.

-Sean


On 7/28/21 12:27 PM, Dimitri John Ledkov wrote:
> Implement revocation list checks. If kernel supports revocation lists,
> check that 2012 canonical signing key is revoked.
>
> Most kernels will skip this test, those kernels that have support for
> revocation lists will check that it is correctly configured and
> visible at runtime.
>
> Signed-off-by: Dimitri John Ledkov <dimitri.ledkov at canonical.com>
> ---
>
>   Note, tested the function in question partially on v5.10 and v5.13
>   kernels. I failed at using the test harness directly to partially
>   execute this test case alone. Thus I am not sure if it runs with
>   python3 or python2, as I was getting exceptions raised from autotest
>   itself.
>
>   ubuntu_boot/control.ubuntu |  1 +
>   ubuntu_boot/ubuntu_boot.py | 30 +++++++++++++++++++++++++++++-
>   2 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/ubuntu_boot/control.ubuntu b/ubuntu_boot/control.ubuntu
> index f73d68c2d3..5f4e3a29bd 100644
> --- a/ubuntu_boot/control.ubuntu
> +++ b/ubuntu_boot/control.ubuntu
> @@ -11,3 +11,4 @@ DOC = '''
>   job.run_test_detail('ubuntu_boot', test_name='log_check', tag='log_check', timeout=60*5)
>   job.run_test_detail('ubuntu_boot', test_name='boot_smoke_test', tag='boot_smoke_test', timeout=60*5)
>   job.run_test_detail('ubuntu_boot', test_name='kernel_tainted', tag='kernel_tainted', timeout=60*5)
> +job.run_test_detail('ubuntu_boot', test_name='kernel_revocation_list', tag='kernel_revocation_list', timeout=60*5)
> diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
> index a67f21d49f..a986210ad3 100644
> --- a/ubuntu_boot/ubuntu_boot.py
> +++ b/ubuntu_boot/ubuntu_boot.py
> @@ -8,7 +8,7 @@ from autotest.client.shared import error
>   class ubuntu_boot(test.test):
>       version = 1
>       def setup(self):
> -        pkgs = [ 'python3' ]
> +        pkgs = [ 'python3', 'keyutils' ]
>           cmd = 'yes "" | DEBIAN_FRONTEND=noninteractive apt-get install --yes --force-yes ' + ' '.join(pkgs)
>           self.results = utils.system_output(cmd, retain_output=True)
>   
> @@ -58,6 +58,31 @@ class ubuntu_boot(test.test):
>           result = utils.system('python3 %s/kernel_taint_test.py' % self.bindir, ignore_status=True)
>           return result
>   
> +    def kernel_revocation_list(self):
> +        '''Test for kernel builtin revoked keys'''
> +        config_file = "/boot/config-" + os.uname().release
> +        revocation_list_available = False
> +        for line in open(config_file):
> +            if re.search("CONFIG_SYSTEM_REVOCATION_LIST", line):
> +                revocation_list_available = True
> +                break
> +        if not revocation_list_available:
> +            print('SKIP: Kernel Revocation List NA.')
> +            raise error.TestNAError()
> +        revocations = utils.system_output("keyctl list %:.blacklist", retain_output=True)
> +        patterns = [
> +            b'.* asymmetric: Canonical Ltd. Secure Boot Signing: 61482aa2830d0ab2ad5af10b7250da9033ddcef0',
> +        ]
> +        missing_patterns = False
> +        for pat in patterns:
> +            print('Scanning for pattern "{}"'.format(pat))
> +            if not re.search(pat, revocations):
> +                print('Pattern not found.')
> +                missing_patterns = True
> +        if missing_patterns:
> +            raise error.TestFail()
> +        print('GOOD: Kernel Revocation List.')
> +
>       def run_once(self, test_name, exit_on_error=True):
>           if test_name == 'log_check':
>               if not self.log_check():
> @@ -71,6 +96,9 @@ class ubuntu_boot(test.test):
>               else:
>                   print('GOOD: Kernel not tainted.')
>               return
> +        elif test_name == 'kernel_revocation_list':
> +            self.kernel_revocation_list()
> +            return
>   
>           cmd = "uname -a"
>           utils.system(cmd)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20210728/db9e3338/attachment.html>


More information about the kernel-team mailing list