1
0
mirror of https://git.yoctoproject.org/poky synced 2026-05-30 12:29:55 +00:00

cve-check: annotate CVEs during analysis

Add status information for each CVE under analysis.

Previously the information passed between different function of the
cve-check class included only tables of patched, unpatched, ignored
vulnerabilities and the general status of the recipe.

The VEX work requires more information, and we need to pass them
between different functions, so that it can be enriched as the
analysis progresses. Instead of multiple tables, use a single one
with annotations for each CVE encountered. For example, a patched
CVE will have:

{"abbrev-status": "Patched", "status": "version-not-in-range"}

abbrev-status contains the general status (Patched, Unpatched,
Ignored and Unknown that will be added in the VEX code)
status contains more detailed information that can come from
CVE_STATUS and the analysis.

Additional fields of the annotation include for example the name
of the patch file fixing a given CVE.

We also use the annotation in CVE_STATUS to filter out entries
that do not apply to the given recipe

(From OE-Core rev: 452e605b55ad61c08f4af7089a5a9c576ca28f7d)

Signed-off-by: Marta Rybczynska <marta.rybczynska@syslinbit.com>
Signed-off-by: Samantha Jalabert <samantha.jalabert@syslinbit.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Marta Rybczynska
2024-08-14 07:30:37 +02:00
committed by Richard Purdie
parent ebc8724416
commit fb3f440b7d
2 changed files with 139 additions and 104 deletions
+29 -6
View File
@@ -88,7 +88,7 @@ def get_patched_cves(d):
# (cve_match regular expression)
cve_file_name_match = re.compile(r".*(CVE-\d{4}-\d+)", re.IGNORECASE)
patched_cves = set()
patched_cves = {}
patches = oe.patch.src_patches(d)
bb.debug(2, "Scanning %d patches for CVEs" % len(patches))
for url in patches:
@@ -98,7 +98,7 @@ def get_patched_cves(d):
fname_match = cve_file_name_match.search(patch_file)
if fname_match:
cve = fname_match.group(1).upper()
patched_cves.add(cve)
patched_cves[cve] = {"abbrev-status": "Patched", "status": "fix-file-included", "resource": patch_file}
bb.debug(2, "Found %s from patch file name %s" % (cve, patch_file))
# Remote patches won't be present and compressed patches won't be
@@ -124,7 +124,7 @@ def get_patched_cves(d):
cves = patch_text[match.start()+5:match.end()]
for cve in cves.split():
bb.debug(2, "Patch %s solves %s" % (patch_file, cve))
patched_cves.add(cve)
patched_cves[cve] = {"abbrev-status": "Patched", "status": "fix-file-included", "resource": patch_file}
text_match = True
if not fname_match and not text_match:
@@ -133,9 +133,15 @@ def get_patched_cves(d):
# Search for additional patched CVEs
for cve in (d.getVarFlags("CVE_STATUS") or {}):
decoded_status = decode_cve_status(d, cve)
if 'mapping' in decoded_status and decoded_status['mapping'] == "Patched":
bb.debug(2, "CVE %s is additionally patched" % cve)
patched_cves.add(cve)
products = d.getVar("CVE_PRODUCT")
if has_cve_product_match(decoded_status, products) == True:
patched_cves[cve] = {
"abbrev-status": decoded_status["mapping"],
"status": decoded_status["detail"],
"justification": decoded_status["description"],
"affected-vendor": decoded_status["vendor"],
"affected-product": decoded_status["product"]
}
return patched_cves
@@ -264,3 +270,20 @@ def decode_cve_status(d, cve):
status_out["mapping"] = status_mapping
return status_out
def has_cve_product_match(detailed_status, products):
"""
Check product/vendor match between detailed_status from decode_cve_status and a string of
products (like from CVE_PRODUCT)
"""
for product in products.split():
vendor = "*"
if ":" in product:
vendor, product = product.split(":", 1)
if (vendor == detailed_status["vendor"] or detailed_status["vendor"] == "*") and \
(product == detailed_status["product"] or detailed_status["product"] == "*"):
return True
#if no match, return False
return False