| Message ID | 20260106204646.3417382-3-valentin.boudevin@gmail.com |
|---|---|
| State | Changes Requested |
| Headers | show |
| Series | generate-cve-exclusions: Add a new bbclass | expand |
> -----Original Message----- > From: openembedded-core@lists.openembedded.org <openembedded- > core@lists.openembedded.org> On Behalf Of vboudevin via > lists.openembedded.org > Sent: Tuesday, 6 January 2026 21:47 > To: openembedded-core@lists.openembedded.org > Cc: ValentinBoudevin <valentin.boudevin@gmail.com> > Subject: [OE-core] [PATCH v3 2/4] generate-cve-exclusions: Add a .bbclass > > Add a .bbclass to generate-cve-exclusions to use this script at every run. > > Two steps for testing: > 1) Inherit this class in the kernel recipe with "inherit > generate-cve-exclusions.bbclass" > 2) Use the following command to generate a cvelistV5 entry with a JSON > file in in ${WORKDIR}/cvelistV5/ : > "bitbake linux-yocto -c generate-cve-exclusions" > > The JSON file can then be parsed in the following run by cve-check. > > This class contains several methods: > > *do_clone_cvelistV5: Clone the cvelistV5 repo in ${WORKDIR}/cvelistV5/git > > (e.g. bitbake-builds/poky-master/build/tmp/work/qemux86_64-poky-linux/ > linux-yocto/6.18.1+git/cvelistV5/git) > > *do_generate_cve_exclusions: Use the script generate-cve-exclusions.py. > It uses the new "--output-json" argument to generate a JSON file as an output > stored in ${WORKDIR}/cvelistV5//cve-exclusion_${LINUX_VERSION}.json > > *do_cve_check:prepend: Parse the previously generated JSON file to set the > variable CVE_STATUS corretly > > Signed-off-by: Valentin Boudevin <valentin.boudevin@gmail.com> > --- > meta/classes/generate-cve-exclusions.bbclass | 67 ++++++++++++++++++++ > 1 file changed, 67 insertions(+) > create mode 100644 meta/classes/generate-cve-exclusions.bbclass > > diff --git a/meta/classes/generate-cve-exclusions.bbclass > b/meta/classes/generate-cve-exclusions.bbclass > new file mode 100644 > index 0000000000..254ea5531d > --- /dev/null > +++ b/meta/classes/generate-cve-exclusions.bbclass > @@ -0,0 +1,67 @@ > +CVE_EXCLUSIONS_WORKDIR ?= "${WORKDIR}/cvelistV5" > +CVELISTV5_PATH ?= "${CVE_EXCLUSIONS_WORKDIR}/git" > + > +python do_clone_cvelistV5() { > + import subprocess > + import shutil, os > + rootdir = d.getVar("CVELISTV5_PATH") > + d.setVar("SRC_URI", > "git://github.com/CVEProject/cvelistV5.git;branch=main;protocol=https") > + d.setVar("SRCREV", "${AUTOREV}") Same comment as the other email regarding AUTOREV and reproducible and offline builds using mirrors. > + src_uri = (d.getVar('SRC_URI') or "").split() > + # Fetch the kernel vulnerabilities sources > + fetcher = bb.fetch2.Fetch(src_uri, d) > + fetcher.download() > + # Unpack into the standard work directory > + fetcher.unpack(rootdir) > + # Remove the folder ${PN} set by unpack > + subdirs = [d for d in os.listdir(rootdir) if os.path.isdir(os.path.join(rootdir, d))] > + if len(subdirs) == 1: > + srcdir = os.path.join(rootdir, subdirs[0]) > + for f in os.listdir(srcdir): > + shutil.move(os.path.join(srcdir, f), rootdir) > + shutil.rmtree(srcdir) > + bb.note("Vulnerabilities repo unpacked into: %s" % rootdir) } > +do_clone_cvelistV5[network] = "1" > +do_clone_cvelistV5[nostamp] = "1" > +do_clone_cvelistV5[doc] = "Clone CVE information from the CVE Project: > https://github.co/ > m%2FCVEProject%2FcvelistV5.git&data=05%7C02%7Cdaniel.turull%40ericsson.c > om%7C3b56ca9a146149d141dd08de4d64bd6f%7C92e84cebfbfd47abbe52080c6 > b87953f%7C0%7C0%7C639033292229191613%7CUnknown%7CTWFpbGZsb3d8 > eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiT > WFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=rvOYYuld78txVFfm1jnu7fo > EP12SNCfxSdN6MHHv4nk%3D&reserved=0" > +addtask clone_cvelistV5 before do_generate_cve_exclusions > + > +do_generate_cve_exclusions() { > + generate_cve_exclusions_script=$(find ${COREBASE} -name "generate-cve- > exclusions.py") > + if [ -z "${generate_cve_exclusions_script}" ]; then > + bbfatal "generate-cve-exclusions.py not found in ${COREBASE}." > + fi > + python3 "${generate_cve_exclusions_script}" \ > + ${CVELISTV5_PATH} \ > + ${LINUX_VERSION} \ > + --output-json > > +${CVE_EXCLUSIONS_WORKDIR}/cve-exclusion_${LINUX_VERSION}.json > +} > +do_generate_cve_exclusions[nostamp] = "1" > +do_generate_cve_exclusions[doc] = "Generate CVE exclusions for the kernel > build. (e.g., cve-exclusion_6.12.inc)" > +addtask generate_cve_exclusions after do_clone_cvelistV5 > + > +python do_cve_check:prepend() { > + import os > + import json > + > + workdir = d.getVar("CVE_EXCLUSIONS_WORKDIR") > + kernel_version = d.getVar("LINUX_VERSION") > + json_input_file = os.path.join(workdir, "cve-exclusion_%s.json" % > + kernel_version) > + > + if os.path.exists(json_input_file): > + with open(json_input_file, 'r', encoding='utf-8') as f: > + cve_data = json.load(f) > + cve_status_dict = cve_data.get("cve_status", {}) > + count = 0 > + for cve_id, info in cve_status_dict.items(): > + if info.get("active", True): > + # Skip active CVEs > + continue > + d.setVarFlag("CVE_STATUS", cve_id, info.get("message", "")) > + count += 1 > + > + bb.note("Loaded %d CVE_STATUS entries from JSON output for kernel %s" > % (count, kernel_version)) > + else: > + bb.warn("CVE exclusion JSON not found: %s. Skipping CVE_STATUS > +updates" % json_input_file) } > \ No newline at end of file
diff --git a/meta/classes/generate-cve-exclusions.bbclass b/meta/classes/generate-cve-exclusions.bbclass new file mode 100644 index 0000000000..254ea5531d --- /dev/null +++ b/meta/classes/generate-cve-exclusions.bbclass @@ -0,0 +1,67 @@ +CVE_EXCLUSIONS_WORKDIR ?= "${WORKDIR}/cvelistV5" +CVELISTV5_PATH ?= "${CVE_EXCLUSIONS_WORKDIR}/git" + +python do_clone_cvelistV5() { + import subprocess + import shutil, os + rootdir = d.getVar("CVELISTV5_PATH") + d.setVar("SRC_URI", "git://github.com/CVEProject/cvelistV5.git;branch=main;protocol=https") + d.setVar("SRCREV", "${AUTOREV}") + src_uri = (d.getVar('SRC_URI') or "").split() + # Fetch the kernel vulnerabilities sources + fetcher = bb.fetch2.Fetch(src_uri, d) + fetcher.download() + # Unpack into the standard work directory + fetcher.unpack(rootdir) + # Remove the folder ${PN} set by unpack + subdirs = [d for d in os.listdir(rootdir) if os.path.isdir(os.path.join(rootdir, d))] + if len(subdirs) == 1: + srcdir = os.path.join(rootdir, subdirs[0]) + for f in os.listdir(srcdir): + shutil.move(os.path.join(srcdir, f), rootdir) + shutil.rmtree(srcdir) + bb.note("Vulnerabilities repo unpacked into: %s" % rootdir) +} +do_clone_cvelistV5[network] = "1" +do_clone_cvelistV5[nostamp] = "1" +do_clone_cvelistV5[doc] = "Clone CVE information from the CVE Project: https://github.com/CVEProject/cvelistV5.git" +addtask clone_cvelistV5 before do_generate_cve_exclusions + +do_generate_cve_exclusions() { + generate_cve_exclusions_script=$(find ${COREBASE} -name "generate-cve-exclusions.py") + if [ -z "${generate_cve_exclusions_script}" ]; then + bbfatal "generate-cve-exclusions.py not found in ${COREBASE}." + fi + python3 "${generate_cve_exclusions_script}" \ + ${CVELISTV5_PATH} \ + ${LINUX_VERSION} \ + --output-json > ${CVE_EXCLUSIONS_WORKDIR}/cve-exclusion_${LINUX_VERSION}.json +} +do_generate_cve_exclusions[nostamp] = "1" +do_generate_cve_exclusions[doc] = "Generate CVE exclusions for the kernel build. (e.g., cve-exclusion_6.12.inc)" +addtask generate_cve_exclusions after do_clone_cvelistV5 + +python do_cve_check:prepend() { + import os + import json + + workdir = d.getVar("CVE_EXCLUSIONS_WORKDIR") + kernel_version = d.getVar("LINUX_VERSION") + json_input_file = os.path.join(workdir, "cve-exclusion_%s.json" % kernel_version) + + if os.path.exists(json_input_file): + with open(json_input_file, 'r', encoding='utf-8') as f: + cve_data = json.load(f) + cve_status_dict = cve_data.get("cve_status", {}) + count = 0 + for cve_id, info in cve_status_dict.items(): + if info.get("active", True): + # Skip active CVEs + continue + d.setVarFlag("CVE_STATUS", cve_id, info.get("message", "")) + count += 1 + + bb.note("Loaded %d CVE_STATUS entries from JSON output for kernel %s" % (count, kernel_version)) + else: + bb.warn("CVE exclusion JSON not found: %s. Skipping CVE_STATUS updates" % json_input_file) +} \ No newline at end of file
Add a .bbclass to generate-cve-exclusions to use this script at every run. Two steps for testing: 1) Inherit this class in the kernel recipe with "inherit generate-cve-exclusions.bbclass" 2) Use the following command to generate a cvelistV5 entry with a JSON file in in ${WORKDIR}/cvelistV5/ : "bitbake linux-yocto -c generate-cve-exclusions" The JSON file can then be parsed in the following run by cve-check. This class contains several methods: *do_clone_cvelistV5: Clone the cvelistV5 repo in ${WORKDIR}/cvelistV5/git (e.g. bitbake-builds/poky-master/build/tmp/work/qemux86_64-poky-linux/ linux-yocto/6.18.1+git/cvelistV5/git) *do_generate_cve_exclusions: Use the script generate-cve-exclusions.py. It uses the new "--output-json" argument to generate a JSON file as an output stored in ${WORKDIR}/cvelistV5//cve-exclusion_${LINUX_VERSION}.json *do_cve_check:prepend: Parse the previously generated JSON file to set the variable CVE_STATUS corretly Signed-off-by: Valentin Boudevin <valentin.boudevin@gmail.com> --- meta/classes/generate-cve-exclusions.bbclass | 67 ++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 meta/classes/generate-cve-exclusions.bbclass