diff options
Diffstat (limited to 'poky/meta/recipes-kernel/linux/generate-cve-exclusions.py')
-rwxr-xr-x | poky/meta/recipes-kernel/linux/generate-cve-exclusions.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/poky/meta/recipes-kernel/linux/generate-cve-exclusions.py b/poky/meta/recipes-kernel/linux/generate-cve-exclusions.py new file mode 100755 index 0000000000..b9b87f245d --- /dev/null +++ b/poky/meta/recipes-kernel/linux/generate-cve-exclusions.py @@ -0,0 +1,101 @@ +#! /usr/bin/env python3 + +# Generate granular CVE status metadata for a specific version of the kernel +# using data from linuxkernelcves.com. +# +# SPDX-License-Identifier: GPL-2.0-only + +import argparse +import datetime +import json +import pathlib +import re + +from packaging.version import Version + + +def parse_version(s): + """ + Parse the version string and either return a packaging.version.Version, or + None if the string was unset or "unk". + """ + if s and s != "unk": + # packaging.version.Version doesn't approve of versions like v5.12-rc1-dontuse + s = s.replace("-dontuse", "") + return Version(s) + return None + + +def main(argp=None): + parser = argparse.ArgumentParser() + parser.add_argument("datadir", type=pathlib.Path, help="Path to a clone of https://github.com/nluedtke/linux_kernel_cves") + parser.add_argument("version", type=Version, help="Kernel version number to generate data for, such as 6.1.38") + + args = parser.parse_args(argp) + datadir = args.datadir + version = args.version + base_version = f"{version.major}.{version.minor}" + + with open(datadir / "data" / "kernel_cves.json", "r") as f: + cve_data = json.load(f) + + with open(datadir / "data" / "stream_fixes.json", "r") as f: + stream_data = json.load(f) + + print(f""" +# Auto-generated CVE metadata, DO NOT EDIT BY HAND. +# Generated at {datetime.datetime.now()} for version {version} + +python check_kernel_cve_status_version() {{ + this_version = "{version}" + kernel_version = d.getVar("LINUX_VERSION") + if kernel_version != this_version: + bb.warn("Kernel CVE status needs updating: generated for %s but kernel is %s" % (this_version, kernel_version)) +}} +do_cve_check[prefuncs] += "check_kernel_cve_status_version" +""") + + for cve, data in cve_data.items(): + if "affected_versions" not in data: + print(f"# Skipping {cve}, no affected_versions") + print() + continue + + affected = data["affected_versions"] + first_affected, last_affected = re.search(r"(.+) to (.+)", affected).groups() + first_affected = parse_version(first_affected) + last_affected = parse_version(last_affected) + + handled = False + if not last_affected: + print(f"# {cve} has no known resolution") + elif first_affected and version < first_affected: + print(f"# fixed-version: only affects {first_affected} onwards") + handled = True + elif last_affected < version: + print(f"# fixed-version: Fixed after version {last_affected}") + handled = True + else: + if cve in stream_data: + backport_data = stream_data[cve] + if base_version in backport_data: + backport_ver = Version(backport_data[base_version]["fixed_version"]) + if backport_ver <= version: + print(f"# cpe-stable-backport: Backported in {backport_ver}") + handled = True + else: + # TODO print a note that the kernel needs bumping + print(f"# {cve} needs backporting (fixed from {backport_ver})") + else: + print(f"# {cve} needs backporting (fixed from {last_affected})") + else: + print(f"# {cve} needs backporting (fixed from {last_affected})") + + if handled: + print(f'CVE_CHECK_IGNORE += "{cve}"') + + print() + + +if __name__ == "__main__": + main() |