mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 12:59:02 +02:00
linux/generate-cve-exclusions: use data from CVEProject
The old script was relying on linuxkernelcves.com that was archived in May 2024 when kernel.org became a CNA. The new script reads CVE json files from the datadir that can be either from the official kernel.org CNA [1] or CVEProject [2] [1] https://git.kernel.org/pub/scm/linux/security/vulns.git [2] https://github.com/CVEProject/cvelistV5 (From OE-Core rev: 12612e8680798bdce39fbb79885e661596dbd53c) Signed-off-by: Daniel Turull <daniel.turull@ericsson.com> Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
f941f64543
commit
33ca2959f2
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
# Generate granular CVE status metadata for a specific version of the kernel
|
||||
# using data from linuxkernelcves.com.
|
||||
# using json data from cvelistV5 or vulns repository
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
|
@ -9,7 +9,8 @@ import argparse
|
|||
import datetime
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import os
|
||||
import glob
|
||||
|
||||
from packaging.version import Version
|
||||
|
||||
|
@ -25,22 +26,75 @@ def parse_version(s):
|
|||
return Version(s)
|
||||
return None
|
||||
|
||||
def get_fixed_versions(cve_info, base_version):
|
||||
'''
|
||||
Get fixed versionss
|
||||
'''
|
||||
first_affected = None
|
||||
fixed = None
|
||||
fixed_backport = None
|
||||
next_version = Version(str(base_version) + ".5000")
|
||||
for affected in cve_info["containers"]["cna"]["affected"]:
|
||||
# In case the CVE info is not complete, it might not have default status and therefore
|
||||
# we don't know the status of this CVE.
|
||||
if not "defaultStatus" in affected:
|
||||
return first_affected, fixed, fixed_backport
|
||||
if affected["defaultStatus"] == "affected":
|
||||
for version in affected["versions"]:
|
||||
v = Version(version["version"])
|
||||
if v == 0:
|
||||
#Skiping non-affected
|
||||
continue
|
||||
if version["status"] == "affected" and not first_affected:
|
||||
first_affected = v
|
||||
elif (version["status"] == "unaffected" and
|
||||
version['versionType'] == "original_commit_for_fix"):
|
||||
fixed = v
|
||||
elif base_version < v and v < next_version:
|
||||
fixed_backport = v
|
||||
elif affected["defaultStatus"] == "unaffected":
|
||||
# Only specific versions are affected. We care only about our base version
|
||||
if "versions" not in affected:
|
||||
continue
|
||||
for version in affected["versions"]:
|
||||
if "versionType" not in version:
|
||||
continue
|
||||
if version["versionType"] == "git":
|
||||
continue
|
||||
v = Version(version["version"])
|
||||
# in case it is not in our base version
|
||||
less_than = Version(version["lessThan"])
|
||||
|
||||
if not first_affected:
|
||||
first_affected = v
|
||||
fixed = less_than
|
||||
if base_version < v and v < next_version:
|
||||
first_affected = v
|
||||
fixed = less_than
|
||||
fixed_backport = less_than
|
||||
|
||||
return first_affected, fixed, fixed_backport
|
||||
|
||||
def is_linux_cve(cve_info):
|
||||
'''Return true is the CVE belongs to Linux'''
|
||||
if not "affected" in cve_info["containers"]["cna"]:
|
||||
return False
|
||||
for affected in cve_info["containers"]["cna"]["affected"]:
|
||||
if not "product" in affected:
|
||||
return False
|
||||
if affected["product"] == "Linux" and affected["vendor"] == "Linux":
|
||||
return True
|
||||
return False
|
||||
|
||||
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("datadir", type=pathlib.Path, help="Path to a clone of https://github.com/CVEProject/cvelistV5 or https://git.kernel.org/pub/scm/linux/security/vulns.git")
|
||||
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)
|
||||
base_version = Version(f"{version.major}.{version.minor}")
|
||||
|
||||
print(f"""
|
||||
# Auto-generated CVE metadata, DO NOT EDIT BY HAND.
|
||||
|
@ -55,17 +109,23 @@ python check_kernel_cve_status_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()
|
||||
# Loop though all CVES and check if they are kernel related, newer than 2015
|
||||
pattern = os.path.join(datadir, '**', "CVE-20*.json")
|
||||
|
||||
files = glob.glob(pattern, recursive=True)
|
||||
for cve_file in sorted(files):
|
||||
# Get CVE Id
|
||||
cve = cve_file[cve_file.rfind("/")+1:cve_file.rfind(".json")]
|
||||
# We process from 2015 data, old request are not properly formated
|
||||
year = cve.split("-")[1]
|
||||
if int(year) < 2015:
|
||||
continue
|
||||
with open(cve_file, 'r', encoding='utf-8') as json_file:
|
||||
cve_info = json.load(json_file)
|
||||
|
||||
affected = data["affected_versions"]
|
||||
first_affected, fixed = re.search(r"(.+) to (.+)", affected).groups()
|
||||
first_affected = parse_version(first_affected)
|
||||
fixed = parse_version(fixed)
|
||||
|
||||
if not is_linux_cve(cve_info):
|
||||
continue
|
||||
first_affected, fixed, backport_ver = get_fixed_versions(cve_info, base_version)
|
||||
if not fixed:
|
||||
print(f"# {cve} has no known resolution")
|
||||
elif first_affected and version < first_affected:
|
||||
|
@ -75,19 +135,13 @@ do_cve_check[prefuncs] += "check_kernel_cve_status_version"
|
|||
f'CVE_STATUS[{cve}] = "fixed-version: Fixed from version {fixed}"'
|
||||
)
|
||||
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'CVE_STATUS[{cve}] = "cpe-stable-backport: Backported in {backport_ver}"'
|
||||
)
|
||||
else:
|
||||
# TODO print a note that the kernel needs bumping
|
||||
print(f"# {cve} needs backporting (fixed from {backport_ver})")
|
||||
if backport_ver:
|
||||
if backport_ver <= version:
|
||||
print(
|
||||
f'CVE_STATUS[{cve}] = "cpe-stable-backport: Backported in {backport_ver}"'
|
||||
)
|
||||
else:
|
||||
print(f"# {cve} needs backporting (fixed from {fixed})")
|
||||
print(f"# {cve} needs backporting (fixed from {backport_ver})")
|
||||
else:
|
||||
print(f"# {cve} needs backporting (fixed from {fixed})")
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user