From 3119c1208037077d13b984cc6863c55ab8fdd869 Mon Sep 17 00:00:00 2001 From: Takahiro Terada Date: Tue, 22 Apr 2025 18:48:40 +0900 Subject: [PATCH] kernel-cve-check: Improve error handling when fetch fails If fetching cip-kernel-sec repository fails, the CVE checks cannot be performed. In this case, output backtrace [1] because there is insufficient error checking. So improve to error handling. When cve-check cannot be performed, there are two ways of thinking depending on the purpose of bitbake: 1. The purpose is build, want to continue to build e.g. `bitbake core-image-minimal` 2. The purpose is cve-check, want to immediately terminate with an error e.g. `bitbake linux-base -c cve_check` Add "CVE_CHECK_ERROR_ON_FAILURE" variable to satisfy these wants. - Set "0" (is default): skip the CVE check and continue with build of bitbake By disabling "CVE_CHECK_DB_FILE" variable, CVE check will be skipped in Poky's do_cve_check() function. This is the same behavior as if the NVD database download failed in Poky, skip the CVE check and continue with build. - Set "1": bitbake return fatal error immediately Immediately exit with bb.fatal(). In summary, the following changes in this commit: - Add exception handling to update_cip_kernel_sec() - Add check of repository synced (Even if fetching cip-kernel-sec repository fails,) A successfully fetched local repository may exist, so if the synced timestamp is today, it is considered a valid repository. - Add error handling logic for "CVE_CHECK_ERROR_ON_FAILURE" variable [1] ``` ERROR: cve-update-nvd2-native-1.0-r0 do_populate_cve_db: Error executing a python function in exec_python_func() autogenerated: The stack trace of python calls that resulted in this exception/failure was: File: 'exec_python_func() autogenerated', lineno: 2, function: 0001: *** 0002:update_cip_kernel_sec(d) 0003: File: '/meta-emlinux/classes/kernel-cve-check.bbclass', lineno: 75, function: update_cip_kernel_sec 0071: os.mkdir(kernel_cve_check_dir) 0072: 0073: if not os.path.isdir(cip_kernel_sec_path): 0074: # first run *** 0075: runfetchcmd("git clone %s cip-kernel-sec" % git_uri, d, workdir=kernel_cve_check_dir) 0076: remove_remote(os.path.join(cip_kernel_sec_path, "conf")) 0077: runfetchcmd("git update-index --skip-worktree conf/remotes.yml", d, workdir=cip_kernel_sec_path) 0078: else: 0079: runfetchcmd("git pull", d, workdir=cip_kernel_sec_path) File: '/poky/bitbake/lib/bb/fetch2/__init__.py', lineno: 886, function: runfetchcmd 0882: bb.utils.remove(f, True) 0883: except OSError: 0884: pass 0885: *** 0886: raise FetchError(error_message) 0887: 0888: return output 0889: 0890:def check_network_access(d, info, url): Exception: bb.fetch2.FetchError: Fetcher failure: Fetch command <...snip...> Cloning into 'cip-kernel-sec'... fatal: unable to access 'https://gitlab.com/cip-project/cip-kernel/cip-kernel-sec.git/': Failed to connect to port : Connection refused ERROR: cve-update-nvd2-native-1.0-r0 do_populate_cve_db: Fetcher failure: Fetch command <...snip...> Cloning into 'cip-kernel-sec'... fatal: unable to access 'https://gitlab.com/cip-project/cip-kernel/cip-kernel-sec.git/': Failed to connect to port : Connection refused ERROR: cve-update-nvd2-native-1.0-r0 do_populate_cve_db: Function failed: update_cip_kernel_sec ERROR: Logfile of failure stored in: /build/tmp-glibc/work/x86_64-linux/cve-update-nvd2-native/1.0-r0/temp/log.do_populate_cve_db.2578823 ERROR: Task (/meta-emlinux/recipes-core/cve-update/cve-update-nvd2-native.bb:do_populate_cve_db) failed with exit code '1' ``` Signed-off-by: Takahiro Terada --- classes/kernel-cve-check.bbclass | 34 +++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/classes/kernel-cve-check.bbclass b/classes/kernel-cve-check.bbclass index 0718b974..2537eb10 100644 --- a/classes/kernel-cve-check.bbclass +++ b/classes/kernel-cve-check.bbclass @@ -16,6 +16,7 @@ inherit cve-check KERNEL_CVE_CHECK_DIR ?= "${CVE_CHECK_DB_DIR}/KERNEL" +CVE_CHECK_ERROR_ON_FAILURE ??= "0" # Consider ignore information. # If value is "0", add CVEs that are registered as negligible to whitelist. @@ -70,13 +71,16 @@ python update_cip_kernel_sec () { if not os.path.isdir(kernel_cve_check_dir): os.mkdir(kernel_cve_check_dir) - if not os.path.isdir(cip_kernel_sec_path): - # first run - runfetchcmd("git clone %s cip-kernel-sec" % git_uri, d, workdir=kernel_cve_check_dir) - remove_remote(os.path.join(cip_kernel_sec_path, "conf")) - runfetchcmd("git update-index --skip-worktree conf/remotes.yml", d, workdir=cip_kernel_sec_path) - else: - runfetchcmd("git pull", d, workdir=cip_kernel_sec_path) + try: + if not os.path.isdir(cip_kernel_sec_path): + # first run + runfetchcmd("git clone %s cip-kernel-sec" % git_uri, d, workdir=kernel_cve_check_dir) + remove_remote(os.path.join(cip_kernel_sec_path, "conf")) + runfetchcmd("git update-index --skip-worktree conf/remotes.yml", d, workdir=cip_kernel_sec_path) + else: + runfetchcmd("git pull", d, workdir=cip_kernel_sec_path) + except Exception as e: + bb.debug(2, "update_cip_kernel_sec: %s, %s" % (git_uri, e)) } do_populate_cve_db[postfuncs] += "update_cip_kernel_sec" @@ -104,6 +108,7 @@ python kernel_cve_check () { import yaml import os import tempfile + from datetime import datetime, date kernel_path = d.getVar("S") linux_cip_ver = d.getVar("LINUX_CIP_VERSION") @@ -118,6 +123,21 @@ python kernel_cve_check () { bb.error("LINUX_CIP_VERSION is not set. Please set version") return + cip_kernel_sec_fetch_head = os.path.join(cip_kernel_sec_path, ".git/FETCH_HEAD") + cve_check_error = True + if os.path.isfile(cip_kernel_sec_fetch_head): + timestamp = datetime.fromtimestamp(os.path.getmtime(cip_kernel_sec_fetch_head)) + if timestamp.date() == date.today(): + cve_check_error = False + + if cve_check_error: + if d.getVar("CVE_CHECK_ERROR_ON_FAILURE") == "0": + d.setVar("CVE_CHECK_DB_FILE", "") + bb.note("kernel_cve_check: cip-kernel-sec repository sync failure, skipping CVE check") + else: + bb.fatal("kernel_cve_check: cip-kernel-sec repository sync failure") + return + opt_ignore = "--include-ignored" if include_ignore == "1" else "" with tempfile.NamedTemporaryFile(delete=False) as f: output_filename = f.name