summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/cve-check.bbclass71
1 files changed, 26 insertions, 45 deletions
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index 743bc08a4f..28619c7bd4 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}/nvd-json.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"
@@ -62,7 +62,7 @@ python do_cve_check () {
62} 62}
63 63
64addtask cve_check after do_unpack before do_build 64addtask 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" 65do_cve_check[depends] = "cve-update-db:do_populate_cve_db"
66do_cve_check[nostamp] = "1" 66do_cve_check[nostamp] = "1"
67 67
68python cve_check_cleanup () { 68python cve_check_cleanup () {
@@ -163,61 +163,40 @@ def get_patches_cves(d):
163 163
164def check_cves(d, patched_cves): 164def check_cves(d, patched_cves):
165 """ 165 """
166 Run cve-check-tool looking for patched and unpatched CVEs. 166 Connect to the NVD database and find unpatched cves.
167 """ 167 """
168
169 import ast, csv, tempfile, subprocess, io 168 import ast, csv, tempfile, subprocess, io
170 169
171 cves_patched = []
172 cves_unpatched = [] 170 cves_unpatched = []
173 bpn = d.getVar("CVE_PRODUCT") 171 bpn = d.getVar("CVE_PRODUCT")
174 # If this has been unset then we're not scanning for CVEs here (for example, image recipes) 172 # If this has been unset then we're not scanning for CVEs here (for example, image recipes)
175 if not bpn: 173 if not bpn:
176 return ([], []) 174 return ([], [])
177 pv = d.getVar("CVE_VERSION").split("+git")[0] 175 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")) 176 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 177
184 # If the recipe has been whitlisted we return empty lists 178 # If the recipe has been whitlisted we return empty lists
185 if d.getVar("PN") in d.getVar("CVE_CHECK_PN_WHITELIST").split(): 179 if d.getVar("PN") in d.getVar("CVE_CHECK_PN_WHITELIST").split():
186 bb.note("Recipe has been whitelisted, skipping check") 180 bb.note("Recipe has been whitelisted, skipping check")
187 return ([], []) 181 return ([], [])
188 182
189 try: 183 import sqlite3
190 # Write the faux CSV file to be used with cve-check-tool 184 db_file = d.getVar("CVE_CHECK_DB_FILE")
191 fd, faux = tempfile.mkstemp(prefix="cve-faux-") 185 conn = sqlite3.connect(db_file)
192 with os.fdopen(fd, "w") as f: 186 c = conn.cursor()
193 for pn in bpn.split(): 187 query = "SELECT * FROM PRODUCTS WHERE PRODUCT IS '%s' AND VERSION IS '%s';"
194 f.write("%s,%s,%s,\n" % (pn, pv, cves)) 188 for row in c.execute(query % (bpn,pv)):
195 cmd.append(faux) 189 cve = row[1]
196 190 if pv in cve_whitelist.get(cve,[]):
197 output = subprocess.check_output(cmd).decode("utf-8") 191 bb.note("%s-%s has been whitelisted for %s" % (bpn, pv, cve))
198 bb.debug(2, "Output of command %s:\n%s" % ("\n".join(cmd), output)) 192 elif cve in patched_cves:
199 except subprocess.CalledProcessError as e: 193 bb.note("%s has been patched" % (cve))
200 bb.warn("Couldn't check for CVEs: %s (output %s)" % (e, e.output)) 194 else:
201 finally: 195 cves_unpatched.append(cve)
202 os.remove(faux) 196 bb.debug(2, "%s-%s is not patched for %s" % (bpn, pv, cve))
203 197 conn.close()
204 for row in csv.reader(io.StringIO(output)): 198
205 # Third row has the unpatched CVEs 199 return (list(patched_cves), cves_unpatched)
206 if row[2]:
207 for cve in row[2].split():
208 # Skip if the CVE has been whitlisted for the current version
209 if pv in cve_whitelist.get(cve,[]):
210 bb.note("%s-%s has been whitelisted for %s" % (bpn, pv, cve))
211 else:
212 cves_unpatched.append(cve)
213 bb.debug(2, "%s-%s is not patched for %s" % (bpn, pv, cve))
214 # Fourth row has patched CVEs
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
220 return (cves_patched, cves_unpatched)
221 200
222def get_cve_info(d, cves): 201def get_cve_info(d, cves):
223 """ 202 """
@@ -241,9 +220,10 @@ def get_cve_info(d, cves):
241 for row in cur.execute(query, tuple(cves)): 220 for row in cur.execute(query, tuple(cves)):
242 cve_data[row[0]] = {} 221 cve_data[row[0]] = {}
243 cve_data[row[0]]["summary"] = row[1] 222 cve_data[row[0]]["summary"] = row[1]
244 cve_data[row[0]]["score"] = row[2] 223 cve_data[row[0]]["scorev2"] = row[2]
245 cve_data[row[0]]["modified"] = row[3] 224 cve_data[row[0]]["scorev3"] = row[3]
246 cve_data[row[0]]["vector"] = row[4] 225 cve_data[row[0]]["modified"] = row[4]
226 cve_data[row[0]]["vector"] = row[5]
247 conn.close() 227 conn.close()
248 228
249 return cve_data 229 return cve_data
@@ -270,7 +250,8 @@ def cve_write_data(d, patched, unpatched, cve_data):
270 unpatched_cves.append(cve) 250 unpatched_cves.append(cve)
271 write_string += "CVE STATUS: Unpatched\n" 251 write_string += "CVE STATUS: Unpatched\n"
272 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"] 252 write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"]
273 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["score"] 253 write_string += "CVSS v2 BASE SCORE: %s\n" % cve_data[cve]["scorev2"]
254 write_string += "CVSS v3 BASE SCORE: %s\n" % cve_data[cve]["scorev3"]
274 write_string += "VECTOR: %s\n" % cve_data[cve]["vector"] 255 write_string += "VECTOR: %s\n" % cve_data[cve]["vector"]
275 write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve) 256 write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve)
276 257