Skip to content

Commit 9f27b5f

Browse files
committed
debian-cve-check: Improve error handling when dst.json download fails
If the Debian Security Tracker json (dst.json) download fails or file is invalid, the CVE check 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 bash -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 load_json() Delete file exist check as they are handled by exception handling. - Add check timestamp of the dst.json file (Even if the dst.json download fails,) A successfully downloaded dst.json file may still exist, so if the timestamp within CVE_DB_UPDATE_INTERVAL (default 24 hours), it is considered a valid file. - Add error handling logic for "CVE_CHECK_ERROR_ON_FAILURE" variable Change the log output lebel to match behavior of this variable. - Some code style fixes Add spaces after comma. [1] ``` File: '<path-to>/meta-debian/classes/debian-cve-check.bbclass', lineno: 33, function: debian_cve_check 0029: _pkg_file_name = os.path.basename(_pkg_uri) 0030: pkgname = _pkg_file_name.split(";")[0].split("_")[0] 0031: break 0032: *** 0033: if pkgname not in dst_data.keys(): 0034: bb.note("%s is not found in Debian Security Tracker." % pkgname) 0035: return 0036: 0037: deb_patched, deb_unpatched = deb_check_cves(d, dst_data[pkgname]) Exception: AttributeError: 'NoneType' object has no attribute 'keys' ``` Signed-off-by: Takahiro Terada <[email protected]>
1 parent c0e0ebe commit 9f27b5f

File tree

2 files changed

+54
-12
lines changed

2 files changed

+54
-12
lines changed

classes/debian-cve-check.bbclass

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,46 @@
1010
DEBIAN_CVE_CHECK_DB_DIR ?= "${CVE_CHECK_DB_DIR}/DEBIAN"
1111
DEBIAN_CODENAME ?= "${DISTRO_CODENAME}"
1212
DEBIAN_SECRUTY_TRACKER_JSON_URL ??= "https://deb.freexian.com/extended-lts/tracker/data/json"
13+
CVE_CHECK_ERROR_ON_FAILURE ??= "0"
14+
15+
# CVE database update interval, in seconds. By default: once a day (24*60*60).
16+
# Use 0 to force the update
17+
# Use a negative value to skip the update
18+
CVE_DB_UPDATE_INTERVAL ??= "86400"
1319

1420
python debian_cve_check () {
1521
"""
1622
Check CVE in Debian source
1723
"""
24+
from datetime import datetime, date
25+
1826
debian_src_uri = d.getVar("DEBIAN_SRC_URI", True)
1927
if debian_src_uri is None:
2028
bb.note("%s dosen't use debian source" % d.getVar("BPN"))
2129
return
2230

23-
json_path = os.path.join(d.getVar("DEBIAN_CVE_CHECK_DB_DIR", True),"dst.json")
24-
dst_data = load_json(json_path)
31+
json_path = os.path.join(d.getVar("DEBIAN_CVE_CHECK_DB_DIR", True), "dst.json")
32+
cve_check_error = True
33+
if os.path.isfile(json_path):
34+
try:
35+
update_interval = int(d.getVar("CVE_DB_UPDATE_INTERVAL"))
36+
except ValueError:
37+
update_interval = 0
38+
if update_interval == 0:
39+
update_interval = 86400
40+
if ((update_interval < 0) or
41+
(time.time() - os.path.getmtime(json_path) < update_interval)):
42+
dst_data = load_json(json_path)
43+
if dst_data is not None:
44+
cve_check_error = False
45+
46+
if cve_check_error:
47+
if d.getVar("CVE_CHECK_ERROR_ON_FAILURE") == "0":
48+
d.setVar("CVE_CHECK_DB_FILE", "")
49+
bb.note("debian_cve_check: No DST database found, skipping CVE check")
50+
else:
51+
bb.fatal("debian_cve_check: No DST database found")
52+
return
2553

2654
# get package name from DEBIAN_SRC_URI
2755
for _pkg_uri in debian_src_uri.split():
@@ -52,15 +80,22 @@ python update_dst () {
5280
from datetime import datetime, date
5381

5482
json_urls = d.getVar("DEBIAN_SECRUTY_TRACKER_JSON_URL", "").split(" ")
55-
dist_path = os.path.join(d.getVar("DEBIAN_CVE_CHECK_DB_DIR", True),"dst.json")
83+
dist_path = os.path.join(d.getVar("DEBIAN_CVE_CHECK_DB_DIR", True), "dst.json")
5684
dist_dir = os.path.dirname(dist_path)
5785

5886
if not os.path.isdir(dist_dir):
5987
os.mkdir(dist_dir)
6088

6189
if os.path.isfile(dist_path):
62-
timestamp = datetime.fromtimestamp(os.path.getmtime(dist_path))
63-
if timestamp.date() == date.today():
90+
try:
91+
update_interval = int(d.getVar("CVE_DB_UPDATE_INTERVAL"))
92+
except ValueError:
93+
update_interval = 0
94+
if update_interval < 0:
95+
bb.note("DST database update skipped")
96+
return
97+
if time.time() - os.path.getmtime(dist_path) < update_interval:
98+
bb.note("DST database recently updated, skipping")
6499
return
65100

66101
for json_url in json_urls:
@@ -79,7 +114,7 @@ python update_dst () {
79114
time.sleep(10 + (attempt * 10))
80115
continue
81116
else:
82-
bb.error("DST database received error")
117+
bb.warn("DST database download failed")
83118
return
84119
}
85120

@@ -90,11 +125,12 @@ def load_json(path):
90125
Load json file.
91126
"""
92127
import json
93-
if not os.path.isfile(path):
94-
bb.error("%s dosen't exist" % path)
128+
try:
129+
with open(path, 'r') as f:
130+
return json.load(f)
131+
except Exception as e:
132+
bb.debug(2, "%s json.load: %s" % (path, e))
95133
return
96-
with open(path, 'r') as f:
97-
return json.load(f)
98134

99135
def deb_check_cves(d, pkg_data):
100136
"""
@@ -132,8 +168,8 @@ def compare_versions(current_version, fixed_version):
132168
"""
133169
import subprocess
134170

135-
ret = subprocess.run(["/usr/bin/dpkg","--compare-versions", current_version,
136-
"ge",fixed_version]).returncode
171+
ret = subprocess.run(["/usr/bin/dpkg", "--compare-versions", current_version,
172+
"ge", fixed_version]).returncode
137173
if ret == 0:
138174
return True
139175
else:

doc/7.cve-check.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ Replace URL:
2222
DEBIAN_SECRUTY_TRACKER_JSON_URL = "http://localhost:8000/dst.json"
2323
```
2424

25+
- CVE\_CHECK\_ERROR\_ON\_FAILURE
26+
27+
If the Debian security tracker json (dst.json) cannot be downloaded or file is invalid, the CVE check cannot be performed.
28+
In this case, set ```CVE_CHECK_ERROR_ON_FAILURE``` to "1" to make bitbake return fatal ERROR.
29+
The default for this variable is "0" to skip the CVE check and continue with bitbake.
30+

0 commit comments

Comments
 (0)