summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorMarta Rybczynska <rybczynska@gmail.com>2024-08-14 07:30:35 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2024-08-20 14:12:40 +0100
commitbf34db143956294d64998beb3a83f46c1e39d9d9 (patch)
treeca71d629cab42168c69584c132ea362bb790c4db /meta
parent326b4303eaf198b7a463d3e6e5037565c22e4823 (diff)
downloadpoky-bf34db143956294d64998beb3a83f46c1e39d9d9.tar.gz
cve-check: encode affected product/vendor in CVE_STATUS
CVE_STATUS contains assesment of a given CVE, but until now it didn't have include the affected vendor/product. In the case of a global system include, that CVE_STATUS was visible in all recipes. This patch allows encoding of affected product/vendor to each CVE_STATUS assessment, also for groups. We can then filter them later and use only CVEs that correspond to the recipe. This is going to be used in meta/conf/distro/include/cve-extra-exclusions.inc and similar places. (From OE-Core rev: abca80a716e92fc18d3085aba1a15f4bac72379c) Signed-off-by: Marta Rybczynska <marta.rybczynska@syslinbit.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/cve-check.bbclass24
-rw-r--r--meta/lib/oe/cve_check.py39
-rw-r--r--meta/lib/oe/spdx30_tasks.py11
3 files changed, 48 insertions, 26 deletions
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index c946de29a4..bc35a1c53c 100644
--- a/meta/classes/cve-check.bbclass
+++ b/meta/classes/cve-check.bbclass
@@ -324,8 +324,8 @@ def check_cves(d, patched_cves):
324 # Convert CVE_STATUS into ignored CVEs and check validity 324 # Convert CVE_STATUS into ignored CVEs and check validity
325 cve_ignore = [] 325 cve_ignore = []
326 for cve in (d.getVarFlags("CVE_STATUS") or {}): 326 for cve in (d.getVarFlags("CVE_STATUS") or {}):
327 decoded_status, _, _ = decode_cve_status(d, cve) 327 decoded_status = decode_cve_status(d, cve)
328 if decoded_status == "Ignored": 328 if 'mapping' in decoded_status and decoded_status['mapping'] == "Ignored":
329 cve_ignore.append(cve) 329 cve_ignore.append(cve)
330 330
331 import sqlite3 331 import sqlite3
@@ -507,11 +507,11 @@ def cve_write_data_text(d, patched, unpatched, ignored, cve_data):
507 write_string += "PACKAGE VERSION: %s%s\n" % (d.getVar("EXTENDPE"), d.getVar("PV")) 507 write_string += "PACKAGE VERSION: %s%s\n" % (d.getVar("EXTENDPE"), d.getVar("PV"))
508 write_string += "CVE: %s\n" % cve 508 write_string += "CVE: %s\n" % cve
509 write_string += "CVE STATUS: %s\n" % status 509 write_string += "CVE STATUS: %s\n" % status
510 _, detail, description = decode_cve_status(d, cve) 510 status_details = decode_cve_status(d, cve)
511 if detail: 511 if 'detail' in status_details:
512 write_string += "CVE DETAIL: %s\n" % detail 512 write_string += "CVE DETAIL: %s\n" % status_details['detail']
513 if description: 513 if 'description' in status_details:
514 write_string += "CVE DESCRIPTION: %s\n" % description 514 write_string += "CVE DESCRIPTION: %s\n" % status_details['description']
515 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"] 515 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"]
516 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"] 516 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"]
517 write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"] 517 write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"]
@@ -637,11 +637,11 @@ def cve_write_data_json(d, patched, unpatched, ignored, cve_data, cve_status):
637 "status" : status, 637 "status" : status,
638 "link": issue_link 638 "link": issue_link
639 } 639 }
640 _, detail, description = decode_cve_status(d, cve) 640 status_details = decode_cve_status(d, cve)
641 if detail: 641 if 'detail' in status_details:
642 cve_item["detail"] = detail 642 cve_item["detail"] = status_details['detail']
643 if description: 643 if 'description' in status_details:
644 cve_item["description"] = description 644 cve_item["description"] = status_details['description']
645 cve_list.append(cve_item) 645 cve_list.append(cve_item)
646 646
647 package_data["issue"] = cve_list 647 package_data["issue"] = cve_list
diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py
index ed5c714cb8..5edd34a2d9 100644
--- a/meta/lib/oe/cve_check.py
+++ b/meta/lib/oe/cve_check.py
@@ -132,8 +132,8 @@ def get_patched_cves(d):
132 132
133 # Search for additional patched CVEs 133 # Search for additional patched CVEs
134 for cve in (d.getVarFlags("CVE_STATUS") or {}): 134 for cve in (d.getVarFlags("CVE_STATUS") or {}):
135 decoded_status, _, _ = decode_cve_status(d, cve) 135 decoded_status = decode_cve_status(d, cve)
136 if decoded_status == "Patched": 136 if 'mapping' in decoded_status and decoded_status['mapping'] == "Patched":
137 bb.debug(2, "CVE %s is additionally patched" % cve) 137 bb.debug(2, "CVE %s is additionally patched" % cve)
138 patched_cves.add(cve) 138 patched_cves.add(cve)
139 139
@@ -227,19 +227,40 @@ def convert_cve_version(version):
227 227
228def decode_cve_status(d, cve): 228def decode_cve_status(d, cve):
229 """ 229 """
230 Convert CVE_STATUS into status, detail and description. 230 Convert CVE_STATUS into status, vendor, product, detail and description.
231 """ 231 """
232 status = d.getVarFlag("CVE_STATUS", cve) 232 status = d.getVarFlag("CVE_STATUS", cve)
233 if not status: 233 if not status:
234 return ("", "", "") 234 return {}
235
236 status_split = status.split(':', 5)
237 status_out = {}
238 status_out["detail"] = status_split[0]
239 product = "*"
240 vendor = "*"
241 description = ""
242 if len(status_split) >= 4 and status_split[1].strip() == "cpe":
243 # Both vendor and product are mandatory if cpe: present, the syntax is then:
244 # detail: cpe:vendor:product:description
245 vendor = status_split[2].strip()
246 product = status_split[3].strip()
247 description = status_split[4].strip()
248 elif len(status_split) >= 2 and status_split[1].strip() == "cpe":
249 # Malformed CPE
250 bb.warn('Invalid CPE information for CVE_STATUS[%s] = "%s", not setting CPE' % (detail, cve, status))
251 else:
252 # Other case: no CPE, the syntax is then:
253 # detail: description
254 description = status_split[len(status_split)-1].strip() if (len(status_split) > 1) else ""
235 255
236 status_split = status.split(':', 1) 256 status_out["vendor"] = vendor
237 detail = status_split[0] 257 status_out["product"] = product
238 description = status_split[1].strip() if (len(status_split) > 1) else "" 258 status_out["description"] = description
239 259
240 status_mapping = d.getVarFlag("CVE_CHECK_STATUSMAP", detail) 260 status_mapping = d.getVarFlag("CVE_CHECK_STATUSMAP", status_out['detail'])
241 if status_mapping is None: 261 if status_mapping is None:
242 bb.warn('Invalid detail "%s" for CVE_STATUS[%s] = "%s", fallback to Unpatched' % (detail, cve, status)) 262 bb.warn('Invalid detail "%s" for CVE_STATUS[%s] = "%s", fallback to Unpatched' % (detail, cve, status))
243 status_mapping = "Unpatched" 263 status_mapping = "Unpatched"
264 status_out["mapping"] = status_mapping
244 265
245 return (status_mapping, detail, description) 266 return status_out
diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py
index 03dc47db02..4864d6252a 100644
--- a/meta/lib/oe/spdx30_tasks.py
+++ b/meta/lib/oe/spdx30_tasks.py
@@ -488,21 +488,22 @@ def create_spdx(d):
488 cve_by_status = {} 488 cve_by_status = {}
489 if include_vex != "none": 489 if include_vex != "none":
490 for cve in d.getVarFlags("CVE_STATUS") or {}: 490 for cve in d.getVarFlags("CVE_STATUS") or {}:
491 status, detail, description = oe.cve_check.decode_cve_status(d, cve) 491 decoded_status = oe.cve_check.decode_cve_status(d, cve)
492 492
493 # If this CVE is fixed upstream, skip it unless all CVEs are 493 # If this CVE is fixed upstream, skip it unless all CVEs are
494 # specified. 494 # specified.
495 if include_vex != "all" and detail in ( 495 if include_vex != "all" and 'detail' in decoded_status and \
496 decoded_status['detail'] in (
496 "fixed-version", 497 "fixed-version",
497 "cpe-stable-backport", 498 "cpe-stable-backport",
498 ): 499 ):
499 bb.debug(1, "Skipping %s since it is already fixed upstream" % cve) 500 bb.debug(1, "Skipping %s since it is already fixed upstream" % cve)
500 continue 501 continue
501 502
502 cve_by_status.setdefault(status, {})[cve] = ( 503 cve_by_status.setdefault(decoded_status['mapping'], {})[cve] = (
503 build_objset.new_cve_vuln(cve), 504 build_objset.new_cve_vuln(cve),
504 detail, 505 decoded_status['detail'],
505 description, 506 decoded_status['description'],
506 ) 507 )
507 508
508 cpe_ids = oe.cve_check.get_cpe_ids(d.getVar("CVE_PRODUCT"), d.getVar("CVE_VERSION")) 509 cpe_ids = oe.cve_check.get_cpe_ids(d.getVar("CVE_PRODUCT"), d.getVar("CVE_VERSION"))