Merge ~ebarretto/ubuntu-cve-tracker:oval-meta-kernel into ubuntu-cve-tracker:master

Proposed by Eduardo Barretto
Status: Merged
Merged at revision: 0defaa0b0b8dbae7c5794aaa8c71f459162712fa
Proposed branch: ~ebarretto/ubuntu-cve-tracker:oval-meta-kernel
Merge into: ubuntu-cve-tracker:master
Diff against target: 191 lines (+78/-57)
2 files modified
scripts/generate-oval (+1/-25)
scripts/oval_lib.py (+77/-32)
Reviewer Review Type Date Requested Status
Ubuntu Security Team Pending
Review via email: mp+437896@code.launchpad.net

Description of the change

This PR tries to solve some kernel false positives caused by meta kernels. To solve it, I removed the meta kernels completely from OVAL. Also it adds some kernel helper functions just to add consistency and reduce code duplication.

To post a comment you must log in.
Revision history for this message
David Fernandez Gonzalez (litios) wrote :

LGTM!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/scripts/generate-oval b/scripts/generate-oval
index 849ef82..b6dd88e 100755
--- a/scripts/generate-oval
+++ b/scripts/generate-oval
@@ -37,7 +37,7 @@ import tempfile
3737
38import apt_pkg38import apt_pkg
39from cve_lib import (kernel_srcs, product_series, load_cve, PRODUCT_UBUNTU, all_releases, eol_releases, devel_release, release_parent, release_name, release_ppa, release_progenitor, needs_oval)39from cve_lib import (kernel_srcs, product_series, load_cve, PRODUCT_UBUNTU, all_releases, eol_releases, devel_release, release_parent, release_name, release_ppa, release_progenitor, needs_oval)
40from kernel_lib import (meta_kernels, kernel_package_abi, kernel_package_version)40from kernel_lib import meta_kernels
41import oval_lib41import oval_lib
42import lpl_common42import lpl_common
4343
@@ -365,30 +365,6 @@ def parse_cve_file(filepath, cache, pkg_filter=None):
365 rel for rel in packages[package]['Releases']365 rel for rel in packages[package]['Releases']
366 if packages[package]['Releases'][rel]['status'] != 'not-applicable'366 if packages[package]['Releases'][rel]['status'] != 'not-applicable'
367 ]:367 ]:
368 # add meta package
369 # handle meta package of subprojects without needing to have them in kernel_lib
370 progenitor = release_progenitor(release)
371 if progenitor:
372 meta_pkg = meta_kernels.get_meta(progenitor, package, quiet=(debug_level < 1))
373 else:
374 meta_pkg = meta_kernels.get_meta(release, package, quiet=(debug_level < 1))
375 if meta_pkg:
376 if meta_pkg not in packages:
377 packages[meta_pkg] = {
378 'Priority': packages[package]['Priority'],
379 'Tags': packages[package]['Tags'],
380 'Releases': {}
381 }
382 if release not in packages[meta_pkg]['Releases']:
383 kernel_status = packages[package]['Releases'][release]
384 # kernel meta packages have a different versioning
385 # scheme derived from the kernel version + kernel abi
386 meta_version = None
387 if 'fix-version' in kernel_status:
388 meta_version = '%s.%s' % (kernel_package_version(kernel_status['fix-version']),
389 kernel_package_abi(kernel_status['fix-version']))
390 packages[meta_pkg]['Releases'][release] = \
391 duplicate_package_status(release, meta_pkg, kernel_status, cache, override_version=meta_version)
392 # add signed package368 # add signed package
393 # handle signed package of subprojects without needing to have them in kernel_lib369 # handle signed package of subprojects without needing to have them in kernel_lib
394 progenitor = release_progenitor(release)370 progenitor = release_progenitor(release)
diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
index 6c7fa7f..e70a6f1 100644
--- a/scripts/oval_lib.py
+++ b/scripts/oval_lib.py
@@ -79,6 +79,35 @@ by updating your system to the following package versions:""".format(cve)
7979
80 return instruction80 return instruction
8181
82def is_kernel_binaries(binaries):
83 reg = re.compile('linux-image-.*')
84 if any(filter(reg.match, binaries)):
85 return True
86 return False
87
88
89""" Using the following kernel uname, we can understand its format:
90 uname -r -> 5.4.0-1059-generic
91 MAJOR_VERSION="5.4.0"
92 ABI="1059"
93 FLAVOUR="generic"
94"""
95def process_kernel_binaries(binaries, oval_format):
96 packages = ' '.join(binaries)
97 parts = re.findall('linux-image-[a-z]*-?([\d|\.]+-)\d+(-[\w|-]+)', packages)
98 if parts:
99 values = set(map(lambda x: x[0], parts))
100 version = ''.join(values)
101 values = set(map(lambda x: x[1], parts))
102 flavours = '|'.join(values)
103 regex = version + '\d+(' + flavours + ')'
104 if oval_format == 'oci':
105 regex = 'linux-image-(?:unsigned-)?' + regex
106 return regex
107
108 return None
109
110
82class OvalGenerator:111class OvalGenerator:
83 supported_oval_elements = ('definition', 'test', 'object', 'state',112 supported_oval_elements = ('definition', 'test', 'object', 'state',
84 'variable')113 'variable')
@@ -138,7 +167,7 @@ class OvalGenerator:
138 'id_base': id_base + len(test_refs),167 'id_base': id_base + len(test_refs),
139 'source-note': header['Source-note']168 'source-note': header['Source-note']
140 }169 }
141 if package.startswith('linux') and self.oval_format == 'dpkg' and pkg['fix-version']:170 if is_kernel_binaries(pkg['binaries']) and pkg['fix-version']:
142 test_ref = self.get_running_kernel_testref(pkg)171 test_ref = self.get_running_kernel_testref(pkg)
143 if test_ref:172 if test_ref:
144 test_refs = test_refs + test_ref173 test_refs = test_refs + test_ref
@@ -277,25 +306,44 @@ class OvalGenerator:
277 </definition>\n""".format(**mapping))306 </definition>\n""".format(**mapping))
278307
279 def get_running_kernel_testref(self, package):308 def get_running_kernel_testref(self, package):
280 """ Using the following kernel uname, we can understand its format:309 uname_regex = process_kernel_binaries(package['binaries'], self.oval_format)
281 uname -r -> 5.4.0-1059-generic310 if uname_regex:
282 MAJOR_VERSION="5.4.0"311 if self.oval_format == 'dpkg':
283 ABI="1059"312 (var_id, var_id_2) = self.get_running_kernel_variable_id(
284 FLAVOUR="generic"313 uname_regex,
285 """314 package['id_base'],
286 for pkg in package['binaries']:315 package['fix-version'])
287 uname = re.search('linux-image-[a-z]*-?([\d|\.]+-)(\d+)(-[\w|-]+)', pkg)316 (ste_id, ste_id_2) = self.get_running_kernel_state_id(
288 if uname:317 uname_regex,
289 uname_regex = uname.group(1) + '\d{' + str(len(uname.group(2))) + '}' + uname.group(3)318 package['id_base'],
290 (var_id, var_id_2) = self.get_running_kernel_variable_id(uname_regex, package['id_base'], package['fix-version'])319 var_id)
291 (ste_id, ste_id_2) = self.get_running_kernel_state_id(uname_regex, package['id_base'], var_id)320 (obj_id, obj_id_2) = self.get_running_kernel_object_id(
292 (obj_id, obj_id_2) = self.get_running_kernel_object_id(package['id_base'], var_id_2)321 package['id_base'], var_id_2)
293 (test_id, test_id_2) = self.get_running_kernel_test_id(uname_regex, package['id_base'], package['name'],322 (test_id, test_id_2) = self.get_running_kernel_test_id(
294 obj_id, ste_id, obj_id_2, ste_id_2)323 uname_regex, package['id_base'], package['name'],
295 return [{'id': test_id, 'comment': 'Is kernel {0} running'.format(package['name']),324 obj_id, ste_id, obj_id_2, ste_id_2)
296 'kernel': uname_regex, 'var_id': var_id}, {'id': test_id_2, 'comment': 'kernel version comparison', 'kernelobj': True}]325 return [{'id': test_id,
297326 'comment': 'Is kernel {0} running'.format(package['name']),
298 return None327 'kernel': uname_regex, 'var_id': var_id},
328 {'id': test_id_2, 'comment': 'kernel version comparison',
329 'kernelobj': True}]
330 else: # OCI
331 object_id = self.get_package_object_id(package['name'],
332 uname_regex,
333 package['id_base'])
334 state_id = self.get_package_version_state_id(package['id_base'],
335 package['fix-version'])
336 test_title = "Does the '{0}' package exist and is the version less than '{1}'?".format(package['name'],
337 package['fix-version'])
338 test_id = self.get_package_test_id(package['name'],
339 package['id_base'],
340 test_title,
341 object_id,
342 state_id)
343 package['note'] = package['name'] + package['note']
344 return [{'id': test_id, 'comment': package['note']}]
345
346 return None
299347
300 def get_oval_test_for_package(self, package):348 def get_oval_test_for_package(self, package):
301 """ create OVAL test and dependent objects for this package status349 """ create OVAL test and dependent objects for this package status
@@ -1314,25 +1362,22 @@ class OvalGeneratorUSN():
1314 return version_map1362 return version_map
13151363
1316 def get_testref(self, version, pkgs, testref_id):1364 def get_testref(self, version, pkgs, testref_id):
1317 reg = re.compile('linux-image-.*')1365 if is_kernel_binaries(pkgs):
1318 if any(filter(reg.match, pkgs)) and self.oval_format == 'dpkg':1366 uname_regex = process_kernel_binaries(pkgs, self.oval_format)
1319 for pkg in pkgs:1367 if uname_regex:
1320 uname = re.search('linux-image-[a-z]*-?([\d|\.]+-)(\d+)(-[\w|-]+)', pkg)1368 if self.oval_format == 'dpkg':
1321 if uname:
1322 # transform pkgs list into string to make it easy to
1323 # get all flavours at once in a list
1324 packages = ' '.join(pkgs)
1325 flavours = set(re.findall('linux-image-[a-z]*-?[\d|\.]+-\d+-([\w|-]+)', packages))
1326 name = uname.group(1) + '\d{' + str(len(uname.group(2))) + '}-(' + '|'.join(flavours) + ')'
1327 new_id = '{0}0'.format(testref_id)1369 new_id = '{0}0'.format(testref_id)
1328 new_id_2 = '{0}0'.format(testref_id + 1)1370 new_id_2 = '{0}0'.format(testref_id + 1)
1329 # kernel has two test_ref:1371 # kernel has two test_ref:
1330 # 1. check if running kernel is of same version and flavour as patched1372 # 1. check if running kernel is of same version and flavour as patched
1331 # 2. check if running kernel is less than patched kernel1373 # 2. check if running kernel is less than patched kernel
1332 return ({'version': version, 'pkgs': [uname.group(0)],1374 return ({'version': version, 'pkgs': pkgs,
1333 'testref_id': new_id, 'kernel': name},1375 'testref_id': new_id, 'kernel': uname_regex},
1334 {'version': version, 'pkgs': pkgs,1376 {'version': version, 'pkgs': pkgs,
1335 'testref_id': new_id_2, 'kernelobj': new_id})1377 'testref_id': new_id_2, 'kernelobj': new_id})
1378 else:
1379 new_id = '{0}0'.format(testref_id)
1380 return({'version': version, 'pkgs': [uname_regex], 'testref_id': new_id}, None)
13361381
1337 return (None, None)1382 return (None, None)
13381383

Subscribers

People subscribed via source and target branches