summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/generate-cve-exclusions.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/generate-cve-exclusions.py')
-rwxr-xr-xmeta/recipes-kernel/linux/generate-cve-exclusions.py98
1 files changed, 98 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/generate-cve-exclusions.py b/meta/recipes-kernel/linux/generate-cve-exclusions.py
new file mode 100755
index 0000000000..aa9195aab4
--- /dev/null
+++ b/meta/recipes-kernel/linux/generate-cve-exclusions.py
@@ -0,0 +1,98 @@
1#! /usr/bin/env python3
2
3# Generate granular CVE status metadata for a specific version of the kernel
4# using data from linuxkernelcves.com.
5#
6# SPDX-License-Identifier: GPL-2.0-only
7
8import argparse
9import datetime
10import json
11import pathlib
12import re
13
14from packaging.version import Version
15
16
17def parse_version(s):
18 """
19 Parse the version string and either return a packaging.version.Version, or
20 None if the string was unset or "unk".
21 """
22 if s and s != "unk":
23 # packaging.version.Version doesn't approve of versions like v5.12-rc1-dontuse
24 s = s.replace("-dontuse", "")
25 return Version(s)
26 return None
27
28
29def main(argp=None):
30 parser = argparse.ArgumentParser()
31 parser.add_argument("datadir", type=pathlib.Path, help="Path to a clone of https://github.com/nluedtke/linux_kernel_cves")
32 parser.add_argument("version", type=Version, help="Kernel version number to generate data for, such as 6.1.38")
33
34 args = parser.parse_args(argp)
35 datadir = args.datadir
36 version = args.version
37 base_version = f"{version.major}.{version.minor}"
38
39 with open(datadir / "data" / "kernel_cves.json", "r") as f:
40 cve_data = json.load(f)
41
42 with open(datadir / "data" / "stream_fixes.json", "r") as f:
43 stream_data = json.load(f)
44
45 print(f"""
46# Auto-generated CVE metadata, DO NOT EDIT BY HAND.
47# Generated at {datetime.datetime.now(datetime.timezone.utc)} for version {version}
48
49python check_kernel_cve_status_version() {{
50 this_version = "{version}"
51 kernel_version = d.getVar("LINUX_VERSION")
52 if kernel_version != this_version:
53 bb.warn("Kernel CVE status needs updating: generated for %s but kernel is %s" % (this_version, kernel_version))
54}}
55do_cve_check[prefuncs] += "check_kernel_cve_status_version"
56""")
57
58 for cve, data in cve_data.items():
59 if "affected_versions" not in data:
60 print(f"# Skipping {cve}, no affected_versions")
61 print()
62 continue
63
64 affected = data["affected_versions"]
65 first_affected, fixed = re.search(r"(.+) to (.+)", affected).groups()
66 first_affected = parse_version(first_affected)
67 fixed = parse_version(fixed)
68
69 if not fixed:
70 print(f"# {cve} has no known resolution")
71 elif first_affected and version < first_affected:
72 print(f'CVE_STATUS[{cve}] = "fixed-version: only affects {first_affected} onwards"')
73 elif fixed <= version:
74 print(
75 f'CVE_STATUS[{cve}] = "fixed-version: Fixed from version {fixed}"'
76 )
77 else:
78 if cve in stream_data:
79 backport_data = stream_data[cve]
80 if base_version in backport_data:
81 backport_ver = Version(backport_data[base_version]["fixed_version"])
82 if backport_ver <= version:
83 print(
84 f'CVE_STATUS[{cve}] = "cpe-stable-backport: Backported in {backport_ver}"'
85 )
86 else:
87 # TODO print a note that the kernel needs bumping
88 print(f"# {cve} needs backporting (fixed from {backport_ver})")
89 else:
90 print(f"# {cve} needs backporting (fixed from {fixed})")
91 else:
92 print(f"# {cve} needs backporting (fixed from {fixed})")
93
94 print()
95
96
97if __name__ == "__main__":
98 main()