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.py101
1 files changed, 101 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..12ae3b0b1d
--- /dev/null
+++ b/meta/recipes-kernel/linux/generate-cve-exclusions.py
@@ -0,0 +1,101 @@
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()} 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, last_affected = re.search(r"(.+) to (.+)", affected).groups()
66 first_affected = parse_version(first_affected)
67 last_affected = parse_version(last_affected)
68
69 handled = False
70 if not last_affected:
71 print(f"# {cve} has no known resolution")
72 elif first_affected and version < first_affected:
73 print(f"# fixed-version: only affects {first_affected} onwards")
74 handled = True
75 elif last_affected < version:
76 print(f"# fixed-version: Fixed after version {last_affected}")
77 handled = True
78 else:
79 if cve in stream_data:
80 backport_data = stream_data[cve]
81 if base_version in backport_data:
82 backport_ver = Version(backport_data[base_version]["fixed_version"])
83 if backport_ver <= version:
84 print(f"# cpe-stable-backport: Backported in {backport_ver}")
85 handled = True
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 {last_affected})")
91 else:
92 print(f"# {cve} needs backporting (fixed from {last_affected})")
93
94 if handled:
95 print(f'CVE_CHECK_WHITELIST += "{cve}"')
96
97 print()
98
99
100if __name__ == "__main__":
101 main()