<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>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. <br>
</p>
<p>Upon testing this patch against a test harness using Focal amd64
vm:</p>
<p><br>
</p>
<pre style="box-sizing: inherit; font-family: monospace, monospace; font-size: 14px; direction: ltr; hyphens: none; tab-size: 4; word-spacing: 0px; overflow-wrap: break-word; background-color: rgb(247, 247, 247); border: 1px solid rgb(205, 205, 205); border-radius: 0.125rem; color: rgb(17, 17, 17); display: block; margin-bottom: 1.5rem; margin-top: 0px; overflow: auto; padding: 0px; text-align: left; text-shadow: none; white-space: pre; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><span id="line-number-83" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">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
</span><span id="line-number-84" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">01:08:17 DEBUG| Persistent state client._record_indent now set to 2
</span><span id="line-number-85" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">01:08:17 DEBUG| Persistent state client.unexpected_reboot now set to ('ubuntu_boot.kernel_revocation_list', 'ubuntu_boot.kernel_revocation_list')
</span><span id="line-number-86" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">01:08:17 DEBUG| Waiting for pid 2357 for 300 seconds
</span><span id="line-number-87" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">01:08:17 WARNI| System python is too old, crash handling disabled
</span><span id="line-number-88" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">01:08:17 ERROR| Exception escaping from test:
</span><span id="line-number-89" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">Traceback (most recent call last):
</span><span id="line-number-90" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/shared/test.py", line 411, in _exec
</span><span id="line-number-91" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> _call_test_function(self.execute, *p_args, **p_dargs)
</span><span id="line-number-92" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/shared/test.py", line 830, in _call_test_function
</span><span id="line-number-93" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> raise error.UnhandledTestFail(e)
</span><span id="line-number-94" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">UnhandledTestFail: Unhandled AttributeError: 'tuple' object has no attribute 'release'
</span><span id="line-number-95" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">Traceback (most recent call last):
</span><span id="line-number-96" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/shared/test.py", line 823, in _call_test_function
</span><span id="line-number-97" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> return func(*args, **dargs)
</span><span id="line-number-98" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/shared/test.py", line 291, in execute
</span><span id="line-number-99" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> postprocess_profiled_run, args, dargs)
</span><span id="line-number-100" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/shared/test.py", line 212, in _call_run_once
</span><span id="line-number-101" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> self.run_once(*args, **dargs)
</span><span id="line-number-102" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/tests/ubuntu_boot/ubuntu_boot.py", line 97, in run_once
</span><span id="line-number-103" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> self.kernel_revocation_list()
</span><span id="line-number-104" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> File "/home/ubuntu/autotest/client/tests/ubuntu_boot/ubuntu_boot.py", line 60, in kernel_revocation_list
</span><span id="line-number-105" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;"> config_file = "/boot/config-" + os.uname().release
</span><span id="line-number-106" style="box-sizing: inherit; counter-increment: line 1; position: relative; width: 100%;">AttributeError: 'tuple' object has no attribute 'release'</span></pre>
<p>Full output here: <a class="moz-txt-link-freetext" href="https://pastebin.canonical.com/p/Zr2jjzsNcr/">https://pastebin.canonical.com/p/Zr2jjzsNcr/</a><br>
</p>
<p>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:</p>
<p>1.) Re-write it all for python2 (no one wants to do that)</p>
<p>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>' ).</p>
<p>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.</p>
<p>-Sean<br>
</p>
<br>
<div class="moz-cite-prefix">On 7/28/21 12:27 PM, Dimitri John
Ledkov wrote:<br>
</div>
<blockquote type="cite"
cite="mid:20210728162716.79507-1-dimitri.ledkov@canonical.com">
<pre class="moz-quote-pre" wrap="">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 <a class="moz-txt-link-rfc2396E" href="mailto:dimitri.ledkov@canonical.com"><dimitri.ledkov@canonical.com></a>
---
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)
</pre>
</blockquote>
</body>
</html>