summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoss Burton <ross.burton@intel.com>2019-12-08 18:35:47 (GMT)
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-12-16 23:11:10 (GMT)
commit593fe7e35267f665dbb37cc0abcc82be55ac67f8 (patch)
tree91bf149b019845a339354d9be48d4aed1b8b6c93
parent53acd121ab1097435812e3922bad7f8ff75f7107 (diff)
downloadpoky-593fe7e35267f665dbb37cc0abcc82be55ac67f8.tar.gz
cve-check: backport rewrite from master
As detailed at [1] the XML feeds provided by NIST are being discontinued on October 9th 2019. As cve-check-tool uses these feeds, cve-check.bbclass will be inoperable after this date. To ensure that cve-check continues working, backport the following commits from master to move away from the unmaintained cve-check-tool to our own Python code that fetches the JSON: 546d14135c5 cve-update-db: New recipe to update CVE database bc144b028f6 cve-check: Remove dependency to cve-check-tool-native 7f62a20b32a cve-check: Manage CVE_PRODUCT with more than one name 3bf63bc6084 cve-check: Consider CVE that affects versions with less than operator c0eabd30d7b cve-update-db: Use std library instead of urllib3 27eb839ee65 cve-check: be idiomatic 09be21f4d17 cve-update-db: Manage proxy if needed. 975793e3825 cve-update-db: do_populate_cve_db depends on do_fetch 0325dd72714 cve-update-db: Catch request.urlopen errors. 4078da92b49 cve-check: Depends on cve-update-db-native f7676e9a38d cve-update-db: Use NVD CPE data to populate PRODUCTS table bc0195be1b1 cve-check: Update unpatched CVE matching c807c2a6409 cve-update-db-native: Skip recipe when cve-check class is not loaded. 07bb8b25e17 cve-check: remove redundant readline CVE whitelisting 5388ed6d137 cve-check-tool: remove 270ac00cb43 cve-check.bbclass: initialize to_append e6bf9000987 cve-check: allow comparison of Vendor as well as Product 91770338f76 cve-update-db-native: use SQL placeholders instead of format strings 7069302a4cc cve-check: Replace CVE_CHECK_CVE_WHITELIST by CVE_CHECK_WHITELIST 78de2cb39d7 cve-update-db-native: Remove hash column from database. 4b301030cf9 cve-update-db-native: use os.path.join instead of + f0d822fad2a cve-update-db: actually inherit native b309840b6aa cve-update-db-native: use executemany() to optimise CPE insertion bb4e53af33d cve-update-db-native: improve metadata parsing 94227459792 cve-update-db-native: clean up JSON fetching 95438d52b73 cve-update-db-native: fix https proxy issues 1f9a963b9ff glibc: exclude child recipes from CVE scanning [1] https://nvd.nist.gov/General/News/XML-Vulnerability-Feed-Retirement (From OE-Core rev: 8c87e78547c598cada1bce92e7b25d85b994e2eb) (From OE-Core rev: beeed02f9831e75c3f773e44d7efc726f1ff859c) Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/cve-check.bbclass142
-rw-r--r--meta/conf/distro/include/maintainers.inc1
-rw-r--r--meta/recipes-core/glibc/glibc-locale.inc3
-rw-r--r--meta/recipes-core/glibc/glibc-mtrace.inc3
-rw-r--r--meta/recipes-core/glibc/glibc-scripts.inc3
-rw-r--r--meta/recipes-core/meta/cve-update-db-native.bb195
-rw-r--r--meta/recipes-devtools/cve-check-tool/cve-check-tool_5.6.4.bb62
-rw-r--r--meta/recipes-devtools/cve-check-tool/files/0001-Fix-freeing-memory-allocated-by-sqlite.patch50
-rw-r--r--meta/recipes-devtools/cve-check-tool/files/0001-curl-allow-overriding-default-CA-certificate-file.patch215
-rw-r--r--meta/recipes-devtools/cve-check-tool/files/0001-print-progress-in-percent-when-downloading-CVE-db.patch135
-rw-r--r--meta/recipes-devtools/cve-check-tool/files/0001-update-Compare-computed-vs-expected-sha256-digit-str.patch52
-rw-r--r--meta/recipes-devtools/cve-check-tool/files/check-for-malloc_trim-before-using-it.patch51
12 files changed, 292 insertions, 620 deletions
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index 743bc08..c00d291 100644
--- a/meta/classes/cve-check.bbclass
+++ b/meta/classes/cve-check.bbclass
@@ -26,7 +26,7 @@ CVE_PRODUCT ??= "${BPN}"
26CVE_VERSION ??= "${PV}" 26CVE_VERSION ??= "${PV}"
27 27
28CVE_CHECK_DB_DIR ?= "${DL_DIR}/CVE_CHECK" 28CVE_CHECK_DB_DIR ?= "${DL_DIR}/CVE_CHECK"
29CVE_CHECK_DB_FILE ?= "${CVE_CHECK_DB_DIR}/nvd.db" 29CVE_CHECK_DB_FILE ?= "${CVE_CHECK_DB_DIR}/nvdcve_1.0.db"
30 30
31CVE_CHECK_LOG ?= "${T}/cve.log" 31CVE_CHECK_LOG ?= "${T}/cve.log"
32CVE_CHECK_TMP_FILE ?= "${TMPDIR}/cve_check" 32CVE_CHECK_TMP_FILE ?= "${TMPDIR}/cve_check"
@@ -37,32 +37,33 @@ CVE_CHECK_COPY_FILES ??= "1"
37CVE_CHECK_CREATE_MANIFEST ??= "1" 37CVE_CHECK_CREATE_MANIFEST ??= "1"
38 38
39# Whitelist for packages (PN) 39# Whitelist for packages (PN)
40CVE_CHECK_PN_WHITELIST = "\ 40CVE_CHECK_PN_WHITELIST ?= ""
41 glibc-locale \
42"
43 41
44# Whitelist for CVE and version of package 42# Whitelist for CVE. If a CVE is found, then it is considered patched.
45CVE_CHECK_CVE_WHITELIST = "{\ 43# The value is a string containing space separated CVE values:
46 'CVE-2014-2524': ('6.3','5.2',), \ 44#
47}" 45# CVE_CHECK_WHITELIST = 'CVE-2014-2524 CVE-2018-1234'
46#
47CVE_CHECK_WHITELIST ?= ""
48 48
49python do_cve_check () { 49python do_cve_check () {
50 """ 50 """
51 Check recipe for patched and unpatched CVEs 51 Check recipe for patched and unpatched CVEs
52 """ 52 """
53 53
54 if os.path.exists(d.getVar("CVE_CHECK_TMP_FILE")): 54 if os.path.exists(d.getVar("CVE_CHECK_DB_FILE")):
55 patched_cves = get_patches_cves(d) 55 patched_cves = get_patches_cves(d)
56 patched, unpatched = check_cves(d, patched_cves) 56 patched, unpatched = check_cves(d, patched_cves)
57 if patched or unpatched: 57 if patched or unpatched:
58 cve_data = get_cve_info(d, patched + unpatched) 58 cve_data = get_cve_info(d, patched + unpatched)
59 cve_write_data(d, patched, unpatched, cve_data) 59 cve_write_data(d, patched, unpatched, cve_data)
60 else: 60 else:
61 bb.note("Failed to update CVE database, skipping CVE check") 61 bb.note("No CVE database found, skipping CVE check")
62
62} 63}
63 64
64addtask cve_check after do_unpack before do_build 65addtask cve_check after do_unpack before do_build
65do_cve_check[depends] = "cve-check-tool-native:do_populate_sysroot cve-check-tool-native:do_populate_cve_db" 66do_cve_check[depends] = "cve-update-db-native:do_populate_cve_db"
66do_cve_check[nostamp] = "1" 67do_cve_check[nostamp] = "1"
67 68
68python cve_check_cleanup () { 69python cve_check_cleanup () {
@@ -163,65 +164,94 @@ def get_patches_cves(d):
163 164
164def check_cves(d, patched_cves): 165def check_cves(d, patched_cves):
165 """ 166 """
166 Run cve-check-tool looking for patched and unpatched CVEs. 167 Connect to the NVD database and find unpatched cves.
167 """ 168 """
168
169 import ast, csv, tempfile, subprocess, io 169 import ast, csv, tempfile, subprocess, io
170 from distutils.version import LooseVersion
170 171
171 cves_patched = []
172 cves_unpatched = [] 172 cves_unpatched = []
173 bpn = d.getVar("CVE_PRODUCT") 173 # CVE_PRODUCT can contain more than one product (eg. curl/libcurl)
174 products = d.getVar("CVE_PRODUCT").split()
174 # If this has been unset then we're not scanning for CVEs here (for example, image recipes) 175 # If this has been unset then we're not scanning for CVEs here (for example, image recipes)
175 if not bpn: 176 if not products:
176 return ([], []) 177 return ([], [])
177 pv = d.getVar("CVE_VERSION").split("+git")[0] 178 pv = d.getVar("CVE_VERSION").split("+git")[0]
178 cves = " ".join(patched_cves)
179 cve_db_dir = d.getVar("CVE_CHECK_DB_DIR")
180 cve_whitelist = ast.literal_eval(d.getVar("CVE_CHECK_CVE_WHITELIST"))
181 cve_cmd = "cve-check-tool"
182 cmd = [cve_cmd, "--no-html", "--skip-update", "--csv", "--not-affected", "-t", "faux", "-d", cve_db_dir]
183 179
184 # If the recipe has been whitlisted we return empty lists 180 # If the recipe has been whitlisted we return empty lists
185 if d.getVar("PN") in d.getVar("CVE_CHECK_PN_WHITELIST").split(): 181 if d.getVar("PN") in d.getVar("CVE_CHECK_PN_WHITELIST").split():
186 bb.note("Recipe has been whitelisted, skipping check") 182 bb.note("Recipe has been whitelisted, skipping check")
187 return ([], []) 183 return ([], [])
188 184
189 try: 185 old_cve_whitelist = d.getVar("CVE_CHECK_CVE_WHITELIST")
190 # Write the faux CSV file to be used with cve-check-tool 186 if old_cve_whitelist:
191 fd, faux = tempfile.mkstemp(prefix="cve-faux-") 187 bb.warn("CVE_CHECK_CVE_WHITELIST is deprecated, please use CVE_CHECK_WHITELIST.")
192 with os.fdopen(fd, "w") as f: 188 cve_whitelist = d.getVar("CVE_CHECK_WHITELIST").split()
193 for pn in bpn.split(): 189
194 f.write("%s,%s,%s,\n" % (pn, pv, cves)) 190 import sqlite3
195 cmd.append(faux) 191 db_file = d.getVar("CVE_CHECK_DB_FILE")
196 192 conn = sqlite3.connect(db_file)
197 output = subprocess.check_output(cmd).decode("utf-8") 193
198 bb.debug(2, "Output of command %s:\n%s" % ("\n".join(cmd), output)) 194 for product in products:
199 except subprocess.CalledProcessError as e: 195 c = conn.cursor()
200 bb.warn("Couldn't check for CVEs: %s (output %s)" % (e, e.output)) 196 if ":" in product:
201 finally: 197 vendor, product = product.split(":", 1)
202 os.remove(faux) 198 c.execute("SELECT * FROM PRODUCTS WHERE PRODUCT IS ? AND VENDOR IS ?", (product, vendor))
203 199 else:
204 for row in csv.reader(io.StringIO(output)): 200 c.execute("SELECT * FROM PRODUCTS WHERE PRODUCT IS ?", (product,))
205 # Third row has the unpatched CVEs 201
206 if row[2]: 202 for row in c:
207 for cve in row[2].split(): 203 cve = row[0]
208 # Skip if the CVE has been whitlisted for the current version 204 version_start = row[3]
209 if pv in cve_whitelist.get(cve,[]): 205 operator_start = row[4]
210 bb.note("%s-%s has been whitelisted for %s" % (bpn, pv, cve)) 206 version_end = row[5]
207 operator_end = row[6]
208
209 if cve in cve_whitelist:
210 bb.note("%s-%s has been whitelisted for %s" % (product, pv, cve))
211 elif cve in patched_cves:
212 bb.note("%s has been patched" % (cve))
213 else:
214 to_append = False
215 if (operator_start == '=' and pv == version_start):
216 cves_unpatched.append(cve)
211 else: 217 else:
218 if operator_start:
219 try:
220 to_append_start = (operator_start == '>=' and LooseVersion(pv) >= LooseVersion(version_start))
221 to_append_start |= (operator_start == '>' and LooseVersion(pv) > LooseVersion(version_start))
222 except:
223 bb.note("%s: Failed to compare %s %s %s for %s" %
224 (product, pv, operator_start, version_start, cve))
225 to_append_start = False
226 else:
227 to_append_start = False
228
229 if operator_end:
230 try:
231 to_append_end = (operator_end == '<=' and LooseVersion(pv) <= LooseVersion(version_end))
232 to_append_end |= (operator_end == '<' and LooseVersion(pv) < LooseVersion(version_end))
233 except:
234 bb.note("%s: Failed to compare %s %s %s for %s" %
235 (product, pv, operator_end, version_end, cve))
236 to_append_end = False
237 else:
238 to_append_end = False
239
240 if operator_start and operator_end:
241 to_append = to_append_start and to_append_end
242 else:
243 to_append = to_append_start or to_append_end
244
245 if to_append:
212 cves_unpatched.append(cve) 246 cves_unpatched.append(cve)
213 bb.debug(2, "%s-%s is not patched for %s" % (bpn, pv, cve)) 247 bb.debug(2, "%s-%s is not patched for %s" % (product, pv, cve))
214 # Fourth row has patched CVEs 248 conn.close()
215 if row[3]:
216 for cve in row[3].split():
217 cves_patched.append(cve)
218 bb.debug(2, "%s-%s is patched for %s" % (bpn, pv, cve))
219 249
220 return (cves_patched, cves_unpatched) 250 return (list(patched_cves), cves_unpatched)
221 251
222def get_cve_info(d, cves): 252def get_cve_info(d, cves):
223 """ 253 """
224 Get CVE information from the database used by cve-check-tool. 254 Get CVE information from the database.
225 255
226 Unfortunately the only way to get CVE info is set the output to 256 Unfortunately the only way to get CVE info is set the output to
227 html (hard to parse) or query directly the database. 257 html (hard to parse) or query directly the database.
@@ -241,9 +271,10 @@ def get_cve_info(d, cves):
241 for row in cur.execute(query, tuple(cves)): 271 for row in cur.execute(query, tuple(cves)):
242 cve_data[row[0]] = {} 272 cve_data[row[0]] = {}
243 cve_data[row[0]]["summary"] = row[1] 273 cve_data[row[0]]["summary"] = row[1]
244 cve_data[row[0]]["score"] = row[2] 274 cve_data[row[0]]["scorev2"] = row[2]
245 cve_data[row[0]]["modified"] = row[3] 275 cve_data[row[0]]["scorev3"] = row[3]
246 cve_data[row[0]]["vector"] = row[4] 276 cve_data[row[0]]["modified"] = row[4]
277 cve_data[row[0]]["vector"] = row[5]
247 conn.close() 278 conn.close()
248 279
249 return cve_data 280 return cve_data
@@ -270,7 +301,8 @@ def cve_write_data(d, patched, unpatched, cve_data):
270 unpatched_cves.append(cve) 301 unpatched_cves.append(cve)
271 write_string += "CVE STATUS: Unpatched\n" 302 write_string += "CVE STATUS: Unpatched\n"
272 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"] 303 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"]
273 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["score"] 304 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"]
305 write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"]
274 write_string += "VECTOR: %s\n" % cve_data[cve]["vector"] 306 write_string += "VECTOR: %s\n" % cve_data[cve]["vector"]
275 write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve) 307 write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve)
276 308
diff --git a/meta/conf/distro/include/maintainers.inc b/meta/conf/distro/include/maintainers.inc
index 672f067..c027901 100644
--- a/meta/conf/distro/include/maintainers.inc
+++ b/meta/conf/distro/include/maintainers.inc
@@ -116,6 +116,7 @@ RECIPE_MAINTAINER_pn-cryptodev-tests = "Robert Yang <liezhi.yang@windriver.com>"
116RECIPE_MAINTAINER_pn-cups = "Chen Qi <Qi.Chen@windriver.com>" 116RECIPE_MAINTAINER_pn-cups = "Chen Qi <Qi.Chen@windriver.com>"
117RECIPE_MAINTAINER_pn-curl = "Armin Kuster <akuster808@gmail.com>" 117RECIPE_MAINTAINER_pn-curl = "Armin Kuster <akuster808@gmail.com>"
118RECIPE_MAINTAINER_pn-cve-check-tool = "Ross Burton <ross.burton@intel.com>" 118RECIPE_MAINTAINER_pn-cve-check-tool = "Ross Burton <ross.burton@intel.com>"
119RECIPE_MAINTAINER_pn-cve-update-db-native = "Ross Burton <ross.burton@intel.com>"
119RECIPE_MAINTAINER_pn-cwautomacros = "Ross Burton <ross.burton@intel.com>" 120RECIPE_MAINTAINER_pn-cwautomacros = "Ross Burton <ross.burton@intel.com>"
120RECIPE_MAINTAINER_pn-db = "Mark Hatle <mark.hatle@windriver.com>" 121RECIPE_MAINTAINER_pn-db = "Mark Hatle <mark.hatle@windriver.com>"
121RECIPE_MAINTAINER_pn-dbus = "Chen Qi <Qi.Chen@windriver.com>" 122RECIPE_MAINTAINER_pn-dbus = "Chen Qi <Qi.Chen@windriver.com>"
diff --git a/meta/recipes-core/glibc/glibc-locale.inc b/meta/recipes-core/glibc/glibc-locale.inc
index 1b676dc..97d83cb 100644
--- a/meta/recipes-core/glibc/glibc-locale.inc
+++ b/meta/recipes-core/glibc/glibc-locale.inc
@@ -95,3 +95,6 @@ do_install () {
95inherit libc-package 95inherit libc-package
96 96
97BBCLASSEXTEND = "nativesdk" 97BBCLASSEXTEND = "nativesdk"
98
99# Don't scan for CVEs as glibc will be scanned
100CVE_PRODUCT = ""
diff --git a/meta/recipes-core/glibc/glibc-mtrace.inc b/meta/recipes-core/glibc/glibc-mtrace.inc
index d703c14..ef9d60e 100644
--- a/meta/recipes-core/glibc/glibc-mtrace.inc
+++ b/meta/recipes-core/glibc/glibc-mtrace.inc
@@ -11,3 +11,6 @@ do_install() {
11 install -d -m 0755 ${D}${bindir} 11 install -d -m 0755 ${D}${bindir}
12 install -m 0755 ${SRC}/mtrace ${D}${bindir}/ 12 install -m 0755 ${SRC}/mtrace ${D}${bindir}/
13} 13}
14
15# Don't scan for CVEs as glibc will be scanned
16CVE_PRODUCT = ""
diff --git a/meta/recipes-core/glibc/glibc-scripts.inc b/meta/recipes-core/glibc/glibc-scripts.inc
index 2a2b415..14a14e4 100644
--- a/meta/recipes-core/glibc/glibc-scripts.inc
+++ b/meta/recipes-core/glibc/glibc-scripts.inc
@@ -18,3 +18,6 @@ do_install() {
18# sotruss script requires sotruss-lib.so (given by libsotruss package), 18# sotruss script requires sotruss-lib.so (given by libsotruss package),
19# to produce trace of the library calls. 19# to produce trace of the library calls.
20RDEPENDS_${PN} += "libsotruss" 20RDEPENDS_${PN} += "libsotruss"
21
22# Don't scan for CVEs as glibc will be scanned
23CVE_PRODUCT = ""
diff --git a/meta/recipes-core/meta/cve-update-db-native.bb b/meta/recipes-core/meta/cve-update-db-native.bb
new file mode 100644
index 0000000..2c427a5
--- /dev/null
+++ b/meta/recipes-core/meta/cve-update-db-native.bb
@@ -0,0 +1,195 @@
1SUMMARY = "Updates the NVD CVE database"
2LICENSE = "MIT"
3
4INHIBIT_DEFAULT_DEPS = "1"
5
6inherit native
7
8deltask do_unpack
9deltask do_patch
10deltask do_configure
11deltask do_compile
12deltask do_install
13deltask do_populate_sysroot
14
15python () {
16 if not d.getVar("CVE_CHECK_DB_FILE"):
17 raise bb.parse.SkipRecipe("Skip recipe when cve-check class is not loaded.")
18}
19
20python do_populate_cve_db() {
21 """
22 Update NVD database with json data feed
23 """
24
25 import sqlite3, urllib, urllib.parse, shutil, gzip
26 from datetime import date
27
28 BASE_URL = "https://nvd.nist.gov/feeds/json/cve/1.0/nvdcve-1.0-"
29 YEAR_START = 2002
30
31 db_dir = os.path.join(d.getVar("DL_DIR"), 'CVE_CHECK')
32 db_file = os.path.join(db_dir, 'nvdcve_1.0.db')
33 json_tmpfile = os.path.join(db_dir, 'nvd.json.gz')
34 proxy = d.getVar("https_proxy")
35
36 if proxy:
37 # instantiate an opener but do not install it as the global
38 # opener unless if we're really sure it's applicable for all
39 # urllib requests
40 proxy_handler = urllib.request.ProxyHandler({'https': proxy})
41 proxy_opener = urllib.request.build_opener(proxy_handler)
42 else:
43 proxy_opener = None
44
45 cve_f = open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a')
46
47 if not os.path.isdir(db_dir):
48 os.mkdir(db_dir)
49
50 # Connect to database
51 conn = sqlite3.connect(db_file)
52 c = conn.cursor()
53
54 initialize_db(c)
55
56 for year in range(YEAR_START, date.today().year + 1):
57 year_url = BASE_URL + str(year)
58 meta_url = year_url + ".meta"
59 json_url = year_url + ".json.gz"
60
61 # Retrieve meta last modified date
62
63 response = None
64
65 if proxy_opener:
66 response = proxy_opener.open(meta_url)
67 else:
68 req = urllib.request.Request(meta_url)
69 response = urllib.request.urlopen(req)
70
71 if response:
72 for l in response.read().decode("utf-8").splitlines():
73 key, value = l.split(":", 1)
74 if key == "lastModifiedDate":
75 last_modified = value
76 break
77 else:
78 bb.warn("Cannot parse CVE metadata, update failed")
79 return
80
81 # Compare with current db last modified date
82 c.execute("select DATE from META where YEAR = ?", (year,))
83 meta = c.fetchone()
84 if not meta or meta[0] != last_modified:
85 # Clear products table entries corresponding to current year
86 c.execute("delete from PRODUCTS where ID like ?", ('CVE-%d%%' % year,))
87
88 # Update db with current year json file
89 try:
90 if proxy_opener:
91 response = proxy_opener.open(json_url)
92 else:
93 req = urllib.request.Request(json_url)
94 response = urllib.request.urlopen(req)
95
96 if response:
97 update_db(c, gzip.decompress(response.read()).decode('utf-8'))
98 c.execute("insert or replace into META values (?, ?)", [year, last_modified])
99 except urllib.error.URLError as e:
100 cve_f.write('Warning: CVE db update error, CVE data is outdated.\n\n')
101 bb.warn("Cannot parse CVE data (%s), update failed" % e.reason)
102 return
103
104 # Update success, set the date to cve_check file.
105 if year == date.today().year:
106 cve_f.write('CVE database update : %s\n\n' % date.today())
107
108 cve_f.close()
109 conn.commit()
110 conn.close()
111}
112
113def initialize_db(c):
114 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)")
115 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \
116 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)")
117 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \
118 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \
119 VERSION_END TEXT, OPERATOR_END TEXT)")
120
121def parse_node_and_insert(c, node, cveId):
122 # Parse children node if needed
123 for child in node.get('children', ()):
124 parse_node_and_insert(c, child, cveId)
125
126 def cpe_generator():
127 for cpe in node.get('cpe_match', ()):
128 if not cpe['vulnerable']:
129 return
130 cpe23 = cpe['cpe23Uri'].split(':')
131 vendor = cpe23[3]
132 product = cpe23[4]
133 version = cpe23[5]
134
135 if version != '*':
136 # Version is defined, this is a '=' match
137 yield [cveId, vendor, product, version, '=', '', '']
138 else:
139 # Parse start version, end version and operators
140 op_start = ''
141 op_end = ''
142 v_start = ''
143 v_end = ''
144
145 if 'versionStartIncluding' in cpe:
146 op_start = '>='
147 v_start = cpe['versionStartIncluding']
148
149 if 'versionStartExcluding' in cpe:
150 op_start = '>'
151 v_start = cpe['versionStartExcluding']
152
153 if 'versionEndIncluding' in cpe:
154 op_end = '<='
155 v_end = cpe['versionEndIncluding']
156
157 if 'versionEndExcluding' in cpe:
158 op_end = '<'
159 v_end = cpe['versionEndExcluding']
160
161 yield [cveId, vendor, product, v_start, op_start, v_end, op_end]
162
163 c.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator())
164
165def update_db(c, jsondata):
166 import json
167 root = json.loads(jsondata)
168
169 for elt in root['CVE_Items']:
170 if not elt['impact']:
171 continue
172
173 cveId = elt['cve']['CVE_data_meta']['ID']
174 cveDesc = elt['cve']['description']['description_data'][0]['value']
175 date = elt['lastModifiedDate']
176 accessVector = elt['impact']['baseMetricV2']['cvssV2']['accessVector']
177 cvssv2 = elt['impact']['baseMetricV2']['cvssV2']['baseScore']
178
179 try:
180 cvssv3 = elt['impact']['baseMetricV3']['cvssV3']['baseScore']
181 except:
182 cvssv3 = 0.0
183
184 c.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)",
185 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector])
186
187 configurations = elt['configurations']['nodes']
188 for config in configurations:
189 parse_node_and_insert(c, config, cveId)
190
191
192addtask do_populate_cve_db before do_fetch
193do_populate_cve_db[nostamp] = "1"
194
195EXCLUDE_FROM_WORLD = "1"
diff --git a/meta/recipes-devtools/cve-check-tool/cve-check-tool_5.6.4.bb b/meta/recipes-devtools/cve-check-tool/cve-check-tool_5.6.4.bb
deleted file mode 100644
index 1c84fb1..0000000
--- a/meta/recipes-devtools/cve-check-tool/cve-check-tool_5.6.4.bb
+++ /dev/null
@@ -1,62 +0,0 @@
1SUMMARY = "cve-check-tool"
2DESCRIPTION = "cve-check-tool is a tool for checking known (public) CVEs.\
3The tool will identify potentially vunlnerable software packages within Linux distributions through version matching."
4HOMEPAGE = "https://github.com/ikeydoherty/cve-check-tool"
5SECTION = "Development/Tools"
6LICENSE = "GPL-2.0+"
7LIC_FILES_CHKSUM = "file://LICENSE;md5=e8c1458438ead3c34974bc0be3a03ed6"
8
9SRC_URI = "https://github.com/ikeydoherty/${BPN}/releases/download/v${PV}/${BP}.tar.xz \
10 file://check-for-malloc_trim-before-using-it.patch \
11 file://0001-print-progress-in-percent-when-downloading-CVE-db.patch \
12 file://0001-curl-allow-overriding-default-CA-certificate-file.patch \
13 file://0001-update-Compare-computed-vs-expected-sha256-digit-str.patch \
14 file://0001-Fix-freeing-memory-allocated-by-sqlite.patch \
15 "
16
17SRC_URI[md5sum] = "c5f4247140fc9be3bf41491d31a34155"
18SRC_URI[sha256sum] = "b8f283be718af8d31232ac1bfc10a0378fb958aaaa49af39168f8acf501e6a5b"
19
20UPSTREAM_CHECK_URI = "https://github.com/ikeydoherty/cve-check-tool/releases"
21
22DEPENDS = "libcheck glib-2.0 json-glib curl libxml2 sqlite3 openssl ca-certificates"
23
24RDEPENDS_${PN} = "ca-certificates"
25
26inherit pkgconfig autotools
27
28EXTRA_OECONF = "--disable-coverage --enable-relative-plugins"
29CFLAGS_append = " -Wno-error=pedantic"
30
31do_populate_cve_db() {
32 if [ "${BB_NO_NETWORK}" = "1" ] ; then
33 bbwarn "BB_NO_NETWORK is set; Can't update cve-check-tool database, new CVEs won't be detected"
34 return
35 fi
36
37 # In case we don't inherit cve-check class, use default values defined in the class.
38 cve_dir="${CVE_CHECK_DB_DIR}"
39 cve_file="${CVE_CHECK_TMP_FILE}"
40
41 [ -z "${cve_dir}" ] && cve_dir="${DL_DIR}/CVE_CHECK"
42 [ -z "${cve_file}" ] && cve_file="${TMPDIR}/cve_check"
43
44 unused="${@bb.utils.export_proxies(d)}"
45 bbdebug 2 "Updating cve-check-tool database located in $cve_dir"
46 # --cacert works around curl-native not finding the CA bundle
47 if cve-check-update --cacert ${sysconfdir}/ssl/certs/ca-certificates.crt -d "$cve_dir" ; then
48 printf "CVE database was updated on %s UTC\n\n" "$(LANG=C date --utc +'%F %T')" > "$cve_file"
49 else
50 bbwarn "Error in executing cve-check-update"
51 if [ "${@'1' if bb.data.inherits_class('cve-check', d) else '0'}" -ne 0 ] ; then
52 bbwarn "Failed to update cve-check-tool database, CVEs won't be checked"
53 fi
54 fi
55}
56
57addtask populate_cve_db after do_populate_sysroot
58do_populate_cve_db[depends] = "cve-check-tool-native:do_populate_sysroot"
59do_populate_cve_db[nostamp] = "1"
60do_populate_cve_db[progress] = "percent"
61
62BBCLASSEXTEND = "native nativesdk"
diff --git a/meta/recipes-devtools/cve-check-tool/files/0001-Fix-freeing-memory-allocated-by-sqlite.patch b/meta/recipes-devtools/cve-check-tool/files/0001-Fix-freeing-memory-allocated-by-sqlite.patch
deleted file mode 100644
index 4a82cf2..0000000
--- a/meta/recipes-devtools/cve-check-tool/files/0001-Fix-freeing-memory-allocated-by-sqlite.patch
+++ /dev/null
@@ -1,50 +0,0 @@
1From a3353429652f83bb8b0316500faa88fa2555542d Mon Sep 17 00:00:00 2001
2From: Peter Marko <peter.marko@siemens.com>
3Date: Thu, 13 Apr 2017 23:09:52 +0200
4Subject: [PATCH] Fix freeing memory allocated by sqlite
5
6Upstream-Status: Backport
7Signed-off-by: Peter Marko <peter.marko@siemens.com>
8---
9 src/core.c | 8 ++++----
10 1 file changed, 4 insertions(+), 4 deletions(-)
11
12diff --git a/src/core.c b/src/core.c
13index 6263031..6788f16 100644
14--- a/src/core.c
15+++ b/src/core.c
16@@ -82,7 +82,7 @@ static bool ensure_table(CveDB *self)
17 rc = sqlite3_exec(self->db, query, NULL, NULL, &err);
18 if (rc != SQLITE_OK) {
19 fprintf(stderr, "ensure_table(): %s\n", err);
20- free(err);
21+ sqlite3_free(err);
22 return false;
23 }
24
25@@ -91,7 +91,7 @@ static bool ensure_table(CveDB *self)
26 rc = sqlite3_exec(self->db, query, NULL, NULL, &err);
27 if (rc != SQLITE_OK) {
28 fprintf(stderr, "ensure_table(): %s\n", err);
29- free(err);
30+ sqlite3_free(err);
31 return false;
32 }
33
34@@ -99,11 +99,11 @@ static bool ensure_table(CveDB *self)
35 rc = sqlite3_exec(self->db, query, NULL, NULL, &err);
36 if (rc != SQLITE_OK) {
37 fprintf(stderr, "ensure_table(): %s\n", err);
38- free(err);
39+ sqlite3_free(err);
40 return false;
41 }
42 if (err) {
43- free(err);
44+ sqlite3_free(err);
45 }
46
47 return true;
48--
492.1.4
50
diff --git a/meta/recipes-devtools/cve-check-tool/files/0001-curl-allow-overriding-default-CA-certificate-file.patch b/meta/recipes-devtools/cve-check-tool/files/0001-curl-allow-overriding-default-CA-certificate-file.patch
deleted file mode 100644
index 3d8ebd1..0000000
--- a/meta/recipes-devtools/cve-check-tool/files/0001-curl-allow-overriding-default-CA-certificate-file.patch
+++ /dev/null
@@ -1,215 +0,0 @@
1From 825a9969dea052b02ba868bdf39e676349f10dce Mon Sep 17 00:00:00 2001
2From: Jussi Kukkonen <jussi.kukkonen@intel.com>
3Date: Thu, 9 Feb 2017 14:51:28 +0200
4Subject: [PATCH] curl: allow overriding default CA certificate file
5
6Similar to curl, --cacert can now be used in cve-check-tool and
7cve-check-update to override the default CA certificate file. Useful
8in cases where the system default is unsuitable (for example,
9out-dated) or broken (as in OE's current native libcurl, which embeds
10a path string from one build host and then uses it on another although
11the right path may have become something different).
12
13Upstream-Status: Submitted [https://github.com/ikeydoherty/cve-check-tool/pull/45]
14
15Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
16
17
18Took Patrick Ohlys original patch from meta-security-isafw, rebased
19on top of other patches.
20
21Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com>
22---
23 src/library/cve-check-tool.h | 1 +
24 src/library/fetch.c | 10 +++++++++-
25 src/library/fetch.h | 3 ++-
26 src/main.c | 5 ++++-
27 src/update-main.c | 4 +++-
28 src/update.c | 12 +++++++-----
29 src/update.h | 2 +-
30 7 files changed, 27 insertions(+), 10 deletions(-)
31
32diff --git a/src/library/cve-check-tool.h b/src/library/cve-check-tool.h
33index e4bb5b1..f89eade 100644
34--- a/src/library/cve-check-tool.h
35+++ b/src/library/cve-check-tool.h
36@@ -43,6 +43,7 @@ typedef struct CveCheckTool {
37 bool bugs; /**<Whether bug tracking is enabled */
38 GHashTable *mapping; /**<CVE Mapping */
39 const char *output_file; /**<Output file, if any */
40+ const char *cacert_file; /**<Non-default SSL certificate file, if any */
41 } CveCheckTool;
42
43 /**
44diff --git a/src/library/fetch.c b/src/library/fetch.c
45index 0fe6d76..8f998c3 100644
46--- a/src/library/fetch.c
47+++ b/src/library/fetch.c
48@@ -60,7 +60,8 @@ static int progress_callback_new(void *ptr, curl_off_t dltotal, curl_off_t dlnow
49 }
50
51 FetchStatus fetch_uri(const char *uri, const char *target, bool verbose,
52- unsigned int start_percent, unsigned int end_percent)
53+ unsigned int start_percent, unsigned int end_percent,
54+ const char *cacert_file)
55 {
56 FetchStatus ret = FETCH_STATUS_FAIL;
57 CURLcode res;
58@@ -74,6 +75,13 @@ FetchStatus fetch_uri(const char *uri, const char *target, bool verbose,
59 return ret;
60 }
61
62+ if (cacert_file) {
63+ res = curl_easy_setopt(curl, CURLOPT_CAINFO, cacert_file);
64+ if (res != CURLE_OK) {
65+ goto bail;
66+ }
67+ }
68+
69 if (stat(target, &st) == 0) {
70 res = curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
71 if (res != CURLE_OK) {
72diff --git a/src/library/fetch.h b/src/library/fetch.h
73index 4cce5d1..836c7d7 100644
74--- a/src/library/fetch.h
75+++ b/src/library/fetch.h
76@@ -29,7 +29,8 @@ typedef enum {
77 * @return A FetchStatus, indicating the operation taken
78 */
79 FetchStatus fetch_uri(const char *uri, const char *target, bool verbose,
80- unsigned int this_percent, unsigned int next_percent);
81+ unsigned int this_percent, unsigned int next_percent,
82+ const char *cacert_file);
83
84 /**
85 * Attempt to extract the given gzipped file
86diff --git a/src/main.c b/src/main.c
87index 8e6f158..ae69d47 100644
88--- a/src/main.c
89+++ b/src/main.c
90@@ -280,6 +280,7 @@ static bool csv_mode = false;
91 static char *modified_stamp = NULL;
92 static gchar *mapping_file = NULL;
93 static gchar *output_file = NULL;
94+static gchar *cacert_file = NULL;
95
96 static GOptionEntry _entries[] = {
97 { "not-patched", 'n', 0, G_OPTION_ARG_NONE, &hide_patched, "Hide patched/addressed CVEs", NULL },
98@@ -294,6 +295,7 @@ static GOptionEntry _entries[] = {
99 { "csv", 'c', 0, G_OPTION_ARG_NONE, &csv_mode, "Output CSV formatted data only", NULL },
100 { "mapping", 'M', 0, G_OPTION_ARG_STRING, &mapping_file, "Path to a mapping file", NULL},
101 { "output-file", 'o', 0, G_OPTION_ARG_STRING, &output_file, "Path to the output file (output plugin specific)", NULL},
102+ { "cacert", 'C', 0, G_OPTION_ARG_STRING, &cacert_file, "Path to the combined SSL certificates file (system default is used if not set)", NULL},
103 { .short_name = 0 }
104 };
105
106@@ -492,6 +494,7 @@ int main(int argc, char **argv)
107
108 quiet = csv_mode || !no_html;
109 self->output_file = output_file;
110+ self->cacert_file = cacert_file;
111
112 if (!csv_mode && self->output_file) {
113 quiet = false;
114@@ -530,7 +533,7 @@ int main(int argc, char **argv)
115 if (status) {
116 fprintf(stderr, "Update of db forced\n");
117 cve_db_unlock();
118- if (!update_db(quiet, db_path->str)) {
119+ if (!update_db(quiet, db_path->str, self->cacert_file)) {
120 fprintf(stderr, "DB update failure\n");
121 goto cleanup;
122 }
123diff --git a/src/update-main.c b/src/update-main.c
124index 2379cfa..c52d9d0 100644
125--- a/src/update-main.c
126+++ b/src/update-main.c
127@@ -43,11 +43,13 @@ the Free Software Foundation; either version 2 of the License, or\n\
128 static gchar *nvds = NULL;
129 static bool _show_version = false;
130 static bool _quiet = false;
131+static const char *_cacert_file = NULL;
132
133 static GOptionEntry _entries[] = {
134 { "nvd-dir", 'd', 0, G_OPTION_ARG_STRING, &nvds, "NVD directory in filesystem", NULL },
135 { "version", 'v', 0, G_OPTION_ARG_NONE, &_show_version, "Show version", NULL },
136 { "quiet", 'q', 0, G_OPTION_ARG_NONE, &_quiet, "Run silently", NULL },
137+ { "cacert", 'C', 0, G_OPTION_ARG_STRING, &_cacert_file, "Path to the combined SSL certificates file (system default is used if not set)", NULL},
138 { .short_name = 0 }
139 };
140
141@@ -88,7 +90,7 @@ int main(int argc, char **argv)
142 goto end;
143 }
144
145- if (update_db(_quiet, db_path->str)) {
146+ if (update_db(_quiet, db_path->str, _cacert_file)) {
147 ret = EXIT_SUCCESS;
148 } else {
149 fprintf(stderr, "Failed to update database\n");
150diff --git a/src/update.c b/src/update.c
151index 070560a..8cb4a39 100644
152--- a/src/update.c
153+++ b/src/update.c
154@@ -267,7 +267,8 @@ static inline void update_end(int fd, const char *update_fname, bool ok)
155
156 static int do_fetch_update(int year, const char *db_dir, CveDB *cve_db,
157 bool db_exist, bool verbose,
158- unsigned int this_percent, unsigned int next_percent)
159+ unsigned int this_percent, unsigned int next_percent,
160+ const char *cacert_file)
161 {
162 const char nvd_uri[] = URI_PREFIX;
163 autofree(cve_string) *uri_meta = NULL;
164@@ -331,14 +332,14 @@ refetch:
165 }
166
167 /* Fetch NVD META file */
168- st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose, this_percent, this_percent);
169+ st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose, this_percent, this_percent, cacert_file);
170 if (st == FETCH_STATUS_FAIL) {
171 fprintf(stderr, "Failed to fetch %s\n", uri_meta->str);
172 return -1;
173 }
174
175 /* Fetch NVD XML file */
176- st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose, this_percent, next_percent);
177+ st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose, this_percent, next_percent, cacert_file);
178 switch (st) {
179 case FETCH_STATUS_FAIL:
180 fprintf(stderr, "Failed to fetch %s\n", uri_data_gz->str);
181@@ -391,7 +392,7 @@ refetch:
182 return 0;
183 }
184
185-bool update_db(bool quiet, const char *db_file)
186+bool update_db(bool quiet, const char *db_file, const char *cacert_file)
187 {
188 autofree(char) *db_dir = NULL;
189 autofree(CveDB) *cve_db = NULL;
190@@ -466,7 +467,8 @@ bool update_db(bool quiet, const char *db_file)
191 if (!quiet)
192 fprintf(stderr, "completed: %u%%\r", start_percent);
193 rc = do_fetch_update(y, db_dir, cve_db, db_exist, !quiet,
194- start_percent, end_percent);
195+ start_percent, end_percent,
196+ cacert_file);
197 switch (rc) {
198 case 0:
199 if (!quiet)
200diff --git a/src/update.h b/src/update.h
201index b8e9911..ceea0c3 100644
202--- a/src/update.h
203+++ b/src/update.h
204@@ -15,7 +15,7 @@ cve_string *get_db_path(const char *path);
205
206 int update_required(const char *db_file);
207
208-bool update_db(bool quiet, const char *db_file);
209+bool update_db(bool quiet, const char *db_file, const char *cacert_file);
210
211
212 /*
213--
2142.1.4
215
diff --git a/meta/recipes-devtools/cve-check-tool/files/0001-print-progress-in-percent-when-downloading-CVE-db.patch b/meta/recipes-devtools/cve-check-tool/files/0001-print-progress-in-percent-when-downloading-CVE-db.patch
deleted file mode 100644
index 8ea6f68..0000000
--- a/meta/recipes-devtools/cve-check-tool/files/0001-print-progress-in-percent-when-downloading-CVE-db.patch
+++ /dev/null
@@ -1,135 +0,0 @@
1From e9ed26cde63f8ca7607a010a518329339f8c02d3 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Andr=C3=A9=20Draszik?= <git@andred.net>
3Date: Mon, 26 Sep 2016 12:12:41 +0100
4Subject: [PATCH] print progress in percent when downloading CVE db
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Upstream-Status: Pending
10Signed-off-by: André Draszik <git@andred.net>
11---
12 src/library/fetch.c | 28 +++++++++++++++++++++++++++-
13 src/library/fetch.h | 3 ++-
14 src/update.c | 16 ++++++++++++----
15 3 files changed, 41 insertions(+), 6 deletions(-)
16
17diff --git a/src/library/fetch.c b/src/library/fetch.c
18index 06d4b30..0fe6d76 100644
19--- a/src/library/fetch.c
20+++ b/src/library/fetch.c
21@@ -37,13 +37,37 @@ static size_t write_func(void *ptr, size_t size, size_t nmemb, struct fetch_t *f
22 return fwrite(ptr, size, nmemb, f->f);
23 }
24
25-FetchStatus fetch_uri(const char *uri, const char *target, bool verbose)
26+struct percent_t {
27+ unsigned int start;
28+ unsigned int end;
29+};
30+
31+static int progress_callback_new(void *ptr, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
32+{
33+ (void) ultotal;
34+ (void) ulnow;
35+
36+ struct percent_t *percent = (struct percent_t *) ptr;
37+
38+ if (dltotal && percent && percent->end >= percent->start) {
39+ unsigned int diff = percent->end - percent->start;
40+ if (diff) {
41+ fprintf(stderr,"completed: %"CURL_FORMAT_CURL_OFF_T"%%\r", percent->start + (diff * dlnow / dltotal));
42+ }
43+ }
44+
45+ return 0;
46+}
47+
48+FetchStatus fetch_uri(const char *uri, const char *target, bool verbose,
49+ unsigned int start_percent, unsigned int end_percent)
50 {
51 FetchStatus ret = FETCH_STATUS_FAIL;
52 CURLcode res;
53 struct stat st;
54 CURL *curl = NULL;
55 struct fetch_t *f = NULL;
56+ struct percent_t percent = { .start = start_percent, .end = end_percent };
57
58 curl = curl_easy_init();
59 if (!curl) {
60@@ -67,6 +91,8 @@ FetchStatus fetch_uri(const char *uri, const char *target, bool verbose)
61 }
62 if (verbose) {
63 (void)curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
64+ (void)curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &percent);
65+ (void)curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback_new);
66 }
67 res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)write_func);
68 if (res != CURLE_OK) {
69diff --git a/src/library/fetch.h b/src/library/fetch.h
70index 70c3779..4cce5d1 100644
71--- a/src/library/fetch.h
72+++ b/src/library/fetch.h
73@@ -28,7 +28,8 @@ typedef enum {
74 * @param verbose Whether to be verbose
75 * @return A FetchStatus, indicating the operation taken
76 */
77-FetchStatus fetch_uri(const char *uri, const char *target, bool verbose);
78+FetchStatus fetch_uri(const char *uri, const char *target, bool verbose,
79+ unsigned int this_percent, unsigned int next_percent);
80
81 /**
82 * Attempt to extract the given gzipped file
83diff --git a/src/update.c b/src/update.c
84index 30fbe96..eaeeefd 100644
85--- a/src/update.c
86+++ b/src/update.c
87@@ -266,7 +266,8 @@ static inline void update_end(int fd, const char *update_fname, bool ok)
88 }
89
90 static int do_fetch_update(int year, const char *db_dir, CveDB *cve_db,
91- bool db_exist, bool verbose)
92+ bool db_exist, bool verbose,
93+ unsigned int this_percent, unsigned int next_percent)
94 {
95 const char nvd_uri[] = URI_PREFIX;
96 autofree(cve_string) *uri_meta = NULL;
97@@ -330,14 +331,14 @@ refetch:
98 }
99
100 /* Fetch NVD META file */
101- st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose);
102+ st = fetch_uri(uri_meta->str, nvdcve_meta->str, verbose, this_percent, this_percent);
103 if (st == FETCH_STATUS_FAIL) {
104 fprintf(stderr, "Failed to fetch %s\n", uri_meta->str);
105 return -1;
106 }
107
108 /* Fetch NVD XML file */
109- st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose);
110+ st = fetch_uri(uri_data_gz->str, nvdcve_data_gz->str, verbose, this_percent, next_percent);
111 switch (st) {
112 case FETCH_STATUS_FAIL:
113 fprintf(stderr, "Failed to fetch %s\n", uri_data_gz->str);
114@@ -459,10 +460,17 @@ bool update_db(bool quiet, const char *db_file)
115 for (int i = YEAR_START; i <= year+1; i++) {
116 int y = i > year ? -1 : i;
117 int rc;
118+ unsigned int start_percent = ((i+0 - YEAR_START) * 100) / (year+2 - YEAR_START);
119+ unsigned int end_percent = ((i+1 - YEAR_START) * 100) / (year+2 - YEAR_START);
120
121- rc = do_fetch_update(y, db_dir, cve_db, db_exist, !quiet);
122+ if (!quiet)
123+ fprintf(stderr, "completed: %u%%\r", start_percent);
124+ rc = do_fetch_update(y, db_dir, cve_db, db_exist, !quiet,
125+ start_percent, end_percent);
126 switch (rc) {
127 case 0:
128+ if (!quiet)
129+ fprintf(stderr,"completed: %u%%\r", end_percent);
130 continue;
131 case ENOMEM:
132 goto oom;
133--
1342.9.3
135
diff --git a/meta/recipes-devtools/cve-check-tool/files/0001-update-Compare-computed-vs-expected-sha256-digit-str.patch b/meta/recipes-devtools/cve-check-tool/files/0001-update-Compare-computed-vs-expected-sha256-digit-str.patch
deleted file mode 100644
index 458c0cc..0000000
--- a/meta/recipes-devtools/cve-check-tool/files/0001-update-Compare-computed-vs-expected-sha256-digit-str.patch
+++ /dev/null
@@ -1,52 +0,0 @@
1From b0426e63c9ac61657e029f689bcb8dd051e752c6 Mon Sep 17 00:00:00 2001
2From: Sergey Popovich <popovich_sergei@mail.ua>
3Date: Fri, 21 Apr 2017 07:32:23 -0700
4Subject: [PATCH] update: Compare computed vs expected sha256 digit string
5 ignoring case
6
7We produce sha256 digest string using %x snprintf()
8qualifier for each byte of digest which uses alphabetic
9characters from "a" to "f" in lower case to represent
10integer values from 10 to 15.
11
12Previously all of the NVD META files supply sha256
13digest string for corresponding XML file in lower case.
14
15However due to some reason this changed recently to
16provide digest digits in upper case causing fetched
17data consistency checks to fail. This prevents database
18from being updated periodically.
19
20While commit c4f6e94 (update: Do not treat sha256 failure
21as fatal if requested) adds useful option to skip
22digest validation at all and thus provides workaround for
23this situation, it might be unacceptable for some
24deployments where we need to ensure that downloaded
25data is consistent before start parsing it and update
26SQLite database.
27
28Use strcasecmp() to compare two digest strings case
29insensitively and addressing this case.
30
31Upstream-Status: Backport
32Signed-off-by: Sergey Popovich <popovich_sergei@mail.ua>
33---
34 src/update.c | 2 +-
35 1 file changed, 1 insertion(+), 1 deletion(-)
36
37diff --git a/src/update.c b/src/update.c
38index 8588f38..3cc6b67 100644
39--- a/src/update.c
40+++ b/src/update.c
41@@ -187,7 +187,7 @@ static bool nvdcve_data_ok(const char *meta, const char *data)
42 snprintf(&csum_data[idx], len, "%02hhx", digest[i]);
43 }
44
45- ret = streq(csum_meta, csum_data);
46+ ret = !strcasecmp(csum_meta, csum_data);
47
48 err_unmap:
49 munmap(buffer, length);
50--
512.11.0
52
diff --git a/meta/recipes-devtools/cve-check-tool/files/check-for-malloc_trim-before-using-it.patch b/meta/recipes-devtools/cve-check-tool/files/check-for-malloc_trim-before-using-it.patch
deleted file mode 100644
index 0774ad9..0000000
--- a/meta/recipes-devtools/cve-check-tool/files/check-for-malloc_trim-before-using-it.patch
+++ /dev/null
@@ -1,51 +0,0 @@
1From ce64633b9733e962b8d8482244301f614d8b5845 Mon Sep 17 00:00:00 2001
2From: Khem Raj <raj.khem@gmail.com>
3Date: Mon, 22 Aug 2016 22:54:24 -0700
4Subject: [PATCH] Check for malloc_trim before using it
5
6malloc_trim is gnu specific and not all libc
7implement it, threfore write a configure check
8to poke for it first and use the define to
9guard its use.
10
11Helps in compiling on musl based systems
12
13Signed-off-by: Khem Raj <raj.khem@gmail.com>
14---
15Upstream-Status: Submitted [https://github.com/ikeydoherty/cve-check-tool/pull/48]
16 configure.ac | 2 ++
17 src/core.c | 4 ++--
18 2 files changed, 4 insertions(+), 2 deletions(-)
19
20diff --git a/configure.ac b/configure.ac
21index d3b66ce..79c3542 100644
22--- a/configure.ac
23+++ b/configure.ac
24@@ -19,6 +19,8 @@ m4_define([json_required_version], [0.16.0])
25 m4_define([openssl_required_version],[1.0.0])
26 # TODO: Set minimum sqlite
27
28+AC_CHECK_FUNCS_ONCE(malloc_trim)
29+
30 PKG_CHECK_MODULES(CVE_CHECK_TOOL,
31 [
32 glib-2.0 >= glib_required_version,
33diff --git a/src/core.c b/src/core.c
34index 6263031..0d5df29 100644
35--- a/src/core.c
36+++ b/src/core.c
37@@ -498,9 +498,9 @@ bool cve_db_load(CveDB *self, const char *fname)
38 }
39
40 b = true;
41-
42+#ifdef HAVE_MALLOC_TRIM
43 malloc_trim(0);
44-
45+#endif
46 xmlFreeTextReader(r);
47 if (fd) {
48 close(fd);
49--
502.9.3
51