Merge ~canonical-kernel-team/+git/autotest-client-tests:phlin/kernel-taint-rework into ~canonical-kernel-team/+git/autotest-client-tests:master

Proposed by Po-Hsu Lin
Status: Merged
Merged at revision: a339c32659bb9e883b64f5ffc0233c68584fd9b6
Proposed branch: ~canonical-kernel-team/+git/autotest-client-tests:phlin/kernel-taint-rework
Merge into: ~canonical-kernel-team/+git/autotest-client-tests:master
Diff against target: 200 lines (+74/-81)
2 files modified
ubuntu_boot/kernel_taint_test.py (+73/-80)
ubuntu_boot/ubuntu_boot.py (+1/-1)
Reviewer Review Type Date Requested Status
Francis Ginther Approve
Review via email: mp+434486@code.launchpad.net

Commit message

BugLink: https://bugs.launchpad.net/1999237

We're using a list to store those modules which will taint the kernel.
However we didn't check why the module is tainted but just ignore them
if they're in the loaded module list.

It will cause a false impression that a module is tainting the kernel
with different issues simply because they're loaded. This was found
while investigating Kinetic RPI boot test result (with database added
in the same logic). Within which only the rpivid_hevc module was
unsigned, but every other modules in the list were printed out for the
unsigned taint as well.

Test output:
  Taint bit value: 13 (unsigned module was loaded)
  Exception made in test script: bcm2835_codec
  Exception made in test script: bcm2835_isp
  Exception made in test script: bcm2835_v4l2
  Exception made in test script: bcm2835_mmal_vchiq
  Exception made in test script: rpivid_hevc
  Exception made in test script: snd_bcm2835
  Exception made in test script: vc_sm_cma
  * Unsigned modules found, but they are expected and OK

Acutal module taint flag:
  snd_bcm2835 - C
  rpivid_hevc - CE
  bcm2835_codec -C
  bcm2835_v4l2 - C
  bcm2835_isp - C
  bcm2835_mmal_vchiq - C
  vc_sm_cma C

Reconstruct kernel_tainted check, use a taint flag dictionary to
filter out known issues for different modules. Ignore them only if the
issue is explicitly recorded in the database.

Also remove the process_GPL_incompatible_modules(), I don't think we
really care if a certain module is using GPL or MIT license. We care
if it's tainting the kernel.

Update the DGX / RPI modules based on actual test result.

Description of the change

Patch tested with DGX B/F and RPI B/F/J, including testing them with entries removed from the database to make sure they will fail as expected.

Example output for F-DGX:
 Running 'python3 /home/ubuntu/autotest/client/tests/ubuntu_boot/kernel_taint_test.py'
 Kernel taint value is 12289
 Taint bit value: 0 (proprietary module was loaded)
 Exception made in test script for: nvidia_drm
 Exception made in test script for: nvidia_modeset
 Exception made in test script for: nvidia
 * Proprietary modules found, but they are expected and OK
 Taint bit value: 12 (externally-built ('out-of-tree') module was loaded)
 Exception made in test script for: nvidia_uvm
 Exception made in test script for: nvidia_drm
 Exception made in test script for: nvidia_modeset
 Exception made in test script for: mlx5_ib
 Exception made in test script for: ib_uverbs
 Exception made in test script for: nvidia
 Exception made in test script for: ib_core
 Exception made in test script for: mlx5_core
 Exception made in test script for: mlxdevm
 Exception made in test script for: auxiliary
 Exception made in test script for: mlxfw
 Exception made in test script for: mlx_compat
 * Out of Tree modules found, but they are expected and OK
 Taint bit value: 13 (unsigned module was loaded)
 Exception made in test script for: mlx5_ib
 Exception made in test script for: ib_uverbs
 Exception made in test script for: ib_core
 Exception made in test script for: mlx5_core
 Exception made in test script for: mlxdevm
 Exception made in test script for: auxiliary
 Exception made in test script for: mlxfw
 Exception made in test script for: mlx_compat
 * Unsigned modules found, but they are expected and OK
 Kernel tainted but in an expected way.
 GOOD: Test Passed.

To post a comment you must log in.
Revision history for this message
Francis Ginther (fginther) wrote :

+1

review: Approve
Revision history for this message
Po-Hsu Lin (cypressyew) wrote :

Applied and pushed, thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/ubuntu_boot/kernel_taint_test.py b/ubuntu_boot/kernel_taint_test.py
2index 93cccdd..59a2cfb 100755
3--- a/ubuntu_boot/kernel_taint_test.py
4+++ b/ubuntu_boot/kernel_taint_test.py
5@@ -61,92 +61,84 @@ def get_modules():
6 return modules
7
8
9-def process_GPL_incompatible_modules(modules):
10- mod_list = []
11- modules = remove_ignored_modules(modules)
12- for mod in modules:
13- cmd = 'modinfo -F license %s' % mod
14- license = check_output(shlex.split(cmd),
15- universal_newlines=True).strip()
16- if "GPL" not in license and "MIT" not in license:
17- mod_list.append((mod, license))
18- return(mod_list)
19-
20-
21 def process_known_issues(issue, modules):
22- mod_list = []
23- issue_flags = {"staging driver was loaded": "C",
24+ '''Filter out known taint flags'''
25+ issue_flags = {"proprietary module was loaded": "P",
26+ "staging driver was loaded": "C",
27 "externally-built ('out-of-tree') module was loaded": "O",
28 "unsigned module was loaded": "E"}
29- modules = remove_ignored_modules(modules)
30- for mod in modules:
31- fn = '/sys/module/{}/taint'.format(mod)
32- with open(fn, 'r') as f:
33- status = f.read()
34- if issue_flags[issue] in status:
35- mod_list.append(mod)
36- return(mod_list)
37-
38-
39-def remove_ignored_modules(modules):
40- # Remove modules we know will fail, but accept
41- dgx_modules = {'focal': ['mlx5_ib',
42- 'ib_uverbs',
43- 'ib_core',
44- 'mlx5_core',
45- 'mlxdevm',
46- 'auxiliary',
47- 'mlxfw',
48- 'mlx_compat'],
49- 'bionic':['ib_iser',
50- 'rdma_cm',
51- 'iw_cm',
52- 'ib_cm',
53- 'mlx5_ib',
54- 'ib_uverbs',
55- 'ib_core',
56- 'mlx5_core',
57- 'mlxfw',
58- 'mdev',
59- 'mlx_compat']}
60- rpi_modules = {'jammy': ['bcm2835_codec',
61- 'bcm2835_isp',
62- 'bcm2835_v4l2',
63- 'bcm2835_mmal_vchiq',
64- 'snd_bcm2835',
65- 'vc_sm_cma'],
66- 'focal': ['bcm2835_codec',
67- 'bcm2835_isp',
68- 'bcm2835_v4l2',
69- 'bcm2835_mmal_vchiq',
70- 'snd_bcm2835',
71- 'vc_sm_cma']}
72- try:
73- series = platform.dist()[2]
74- except AttributeError:
75- import distro
76- series = distro.codename()
77+ dgx_modules = {'focal': {'nvidia_uvm': 'O',
78+ 'nvidia_drm': 'PO',
79+ 'nvidia_modeset': 'PO',
80+ 'nvidia': 'PO',
81+ 'mlx5_ib': 'OE',
82+ 'ib_uverbs': 'OE',
83+ 'ib_core': 'OE',
84+ 'mlx5_core': 'OE',
85+ 'mlxdevm': 'OE',
86+ 'auxiliary': 'OE',
87+ 'mlxfw': 'OE',
88+ 'mlx_compat': 'OE'},
89+ 'bionic': {'nvidia_uvm': 'O',
90+ 'nvidia_drm': 'PO',
91+ 'nvidia_modeset': 'PO',
92+ 'nvidia': 'PO',
93+ 'ib_iser': 'OE',
94+ 'rdma_cm': 'OE',
95+ 'iw_cm': 'OE',
96+ 'ib_cm': 'OE',
97+ 'mlx5_ib': 'OE',
98+ 'ib_uverbs': 'OE',
99+ 'ib_core': 'OE',
100+ 'mlx5_core': 'OE',
101+ 'mlxfw': 'OE',
102+ 'mdev': 'OE',
103+ 'mlx_compat': 'OE'}}
104+ rpi_modules = {'jammy': {'bcm2835_codec': 'C',
105+ 'bcm2835_isp': 'C',
106+ 'bcm2835_v4l2': 'C',
107+ 'bcm2835_mmal_vchiq': 'C',
108+ 'snd_bcm2835': 'C',
109+ 'vc_sm_cma': 'C'},
110+ 'focal': {'bcm2835_codec': 'CE',
111+ 'bcm2835_isp': 'CE',
112+ 'bcm2835_v4l2': 'CE',
113+ 'bcm2835_mmal_vchiq': 'CE',
114+ 'snd_bcm2835': 'CE',
115+ 'vc_sm_cma': 'CE'}}
116 try:
117 with open('/sys/class/dmi/id/product_name', 'r') as f:
118 product_name = f.read().strip()
119 except FileNotFoundError:
120 product_name = ''
121
122- if series in ['focal', 'bionic'] and 'DGX' in product_name:
123- for ignore_mod in dgx_modules[series]:
124- try:
125- print('Exception made in test script: {}'.format(ignore_mod))
126- modules.remove(ignore_mod)
127- except ValueError:
128- pass
129- elif series in ['focal', 'jammy'] and 'raspi' in platform.release():
130- for ignore_mod in rpi_modules[series]:
131- try:
132- print('Exception made in test script: {}'.format(ignore_mod))
133- modules.remove(ignore_mod)
134- except ValueError:
135- pass
136- return(modules)
137+ module_flags = {}
138+ if 'DGX' in product_name:
139+ module_flags = dgx_modules
140+ elif 'raspi' in platform.release():
141+ module_flags = rpi_modules
142+
143+ try:
144+ series = platform.dist()[2]
145+ except AttributeError:
146+ import distro
147+ series = distro.codename()
148+
149+ # Filter out modules flagged with corresponding taint flag
150+ mod_list = []
151+ for mod in modules:
152+ fn = '/sys/module/{}/taint'.format(mod)
153+ with open(fn, 'r') as f:
154+ status = f.read()
155+ if issue_flags[issue] in status:
156+ # Check with the allow list
157+ if series in module_flags:
158+ if mod in module_flags[series]:
159+ if issue_flags[issue] in module_flags[series][mod]:
160+ print('Exception made in test script for: ' + mod)
161+ continue
162+ mod_list.append(mod)
163+ return mod_list
164
165
166 def main():
167@@ -184,7 +176,7 @@ def main():
168 modules = get_modules()
169 print("Taint bit value: {} ({})".format(i, taint_meanings[i]))
170 if i == 0: # List GPL incompatible modules and licenses
171- proprietary_modules = process_GPL_incompatible_modules(modules)
172+ proprietary_modules = process_known_issues(taint_meanings[i], modules)
173 if proprietary_modules:
174 print("* Modules with GPL Incompatible Licenses:")
175 for mod in proprietary_modules:
176@@ -230,8 +222,9 @@ def main():
177
178
179 if count == 0:
180- # else case below contains expected issue in case 0 / 11 / 12 / 13
181- if not taints:
182+ if taints:
183+ print("Kernel tainted but in an expected way.")
184+ else:
185 print("No kernel taints detected.")
186 return 0
187 else:
188diff --git a/ubuntu_boot/ubuntu_boot.py b/ubuntu_boot/ubuntu_boot.py
189index 50cb8c3..44a0b9b 100644
190--- a/ubuntu_boot/ubuntu_boot.py
191+++ b/ubuntu_boot/ubuntu_boot.py
192@@ -74,7 +74,7 @@ class ubuntu_boot(test.test):
193 if self.kernel_tainted():
194 raise error.TestFail()
195 else:
196- print('GOOD: Kernel not tainted.')
197+ print('GOOD: Test Passed.')
198 return
199 elif test_name == 'kernel_revocation_list':
200 if self.kernel_revocation_list():

Subscribers

People subscribed via source and target branches

to all changes: