summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorRoss Burton <ross.burton@arm.com>2022-08-26 18:35:47 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-09-12 08:41:47 +0100
commit4384b8a13ae515e6d6b2a8375a9fc1a11e5b6e76 (patch)
tree3ece650c9f318b963497f058ccc9eee001d50a32 /meta
parent8856232de42099654a5d2cc8bc422d1e430a0ab4 (diff)
downloadpoky-4384b8a13ae515e6d6b2a8375a9fc1a11e5b6e76.tar.gz
cve-check: close cursors as soon as possible
We can have multiple processes reading the database at the same time, and cursors only release their locks when they're garbage collected. This might be the cause of random sqlite errors on the autobuilder, so explicitly close the cursors when we're done with them. (From OE-Core rev: 90917cadeb7201e56c74294e9156fe899d5455d7) Signed-off-by: Ross Burton <ross.burton@arm.com> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com> (cherry picked from commit 5d2e90e4a58217a943ec21140bc2ecdd4357a98a) Signed-off-by: Steve Sakoman <steve@sakoman.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/cve-check.bbclass13
-rw-r--r--meta/recipes-core/meta/cve-update-db-native.bb51
2 files changed, 37 insertions, 27 deletions
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index b751c986ef..16466586a7 100644
--- a/meta/classes/cve-check.bbclass
+++ b/meta/classes/cve-check.bbclass
@@ -291,7 +291,8 @@ def check_cves(d, patched_cves):
291 vendor = "%" 291 vendor = "%"
292 292
293 # Find all relevant CVE IDs. 293 # Find all relevant CVE IDs.
294 for cverow in conn.execute("SELECT DISTINCT ID FROM PRODUCTS WHERE PRODUCT IS ? AND VENDOR LIKE ?", (product, vendor)): 294 cve_cursor = conn.execute("SELECT DISTINCT ID FROM PRODUCTS WHERE PRODUCT IS ? AND VENDOR LIKE ?", (product, vendor))
295 for cverow in cve_cursor:
295 cve = cverow[0] 296 cve = cverow[0]
296 297
297 if cve in cve_ignore: 298 if cve in cve_ignore:
@@ -310,7 +311,8 @@ def check_cves(d, patched_cves):
310 vulnerable = False 311 vulnerable = False
311 ignored = False 312 ignored = False
312 313
313 for row in conn.execute("SELECT * FROM PRODUCTS WHERE ID IS ? AND PRODUCT IS ? AND VENDOR LIKE ?", (cve, product, vendor)): 314 product_cursor = conn.execute("SELECT * FROM PRODUCTS WHERE ID IS ? AND PRODUCT IS ? AND VENDOR LIKE ?", (cve, product, vendor))
315 for row in product_cursor:
314 (_, _, _, version_start, operator_start, version_end, operator_end) = row 316 (_, _, _, version_start, operator_start, version_end, operator_end) = row
315 #bb.debug(2, "Evaluating row " + str(row)) 317 #bb.debug(2, "Evaluating row " + str(row))
316 if cve in cve_ignore: 318 if cve in cve_ignore:
@@ -354,10 +356,12 @@ def check_cves(d, patched_cves):
354 bb.note("%s-%s is vulnerable to %s" % (pn, real_pv, cve)) 356 bb.note("%s-%s is vulnerable to %s" % (pn, real_pv, cve))
355 cves_unpatched.append(cve) 357 cves_unpatched.append(cve)
356 break 358 break
359 product_cursor.close()
357 360
358 if not vulnerable: 361 if not vulnerable:
359 bb.note("%s-%s is not vulnerable to %s" % (pn, real_pv, cve)) 362 bb.note("%s-%s is not vulnerable to %s" % (pn, real_pv, cve))
360 patched_cves.add(cve) 363 patched_cves.add(cve)
364 cve_cursor.close()
361 365
362 if not cves_in_product: 366 if not cves_in_product:
363 bb.note("No CVE records found for product %s, pn %s" % (product, pn)) 367 bb.note("No CVE records found for product %s, pn %s" % (product, pn))
@@ -382,14 +386,15 @@ def get_cve_info(d, cves):
382 conn = sqlite3.connect(db_file, uri=True) 386 conn = sqlite3.connect(db_file, uri=True)
383 387
384 for cve in cves: 388 for cve in cves:
385 for row in conn.execute("SELECT * FROM NVD WHERE ID IS ?", (cve,)): 389 cursor = conn.execute("SELECT * FROM NVD WHERE ID IS ?", (cve,))
390 for row in cursor:
386 cve_data[row[0]] = {} 391 cve_data[row[0]] = {}
387 cve_data[row[0]]["summary"] = row[1] 392 cve_data[row[0]]["summary"] = row[1]
388 cve_data[row[0]]["scorev2"] = row[2] 393 cve_data[row[0]]["scorev2"] = row[2]
389 cve_data[row[0]]["scorev3"] = row[3] 394 cve_data[row[0]]["scorev3"] = row[3]
390 cve_data[row[0]]["modified"] = row[4] 395 cve_data[row[0]]["modified"] = row[4]
391 cve_data[row[0]]["vector"] = row[5] 396 cve_data[row[0]]["vector"] = row[5]
392 397 cursor.close()
393 conn.close() 398 conn.close()
394 return cve_data 399 return cve_data
395 400
diff --git a/meta/recipes-core/meta/cve-update-db-native.bb b/meta/recipes-core/meta/cve-update-db-native.bb
index 18af89b53e..944243fce9 100644
--- a/meta/recipes-core/meta/cve-update-db-native.bb
+++ b/meta/recipes-core/meta/cve-update-db-native.bb
@@ -66,9 +66,7 @@ python do_fetch() {
66 66
67 # Connect to database 67 # Connect to database
68 conn = sqlite3.connect(db_file) 68 conn = sqlite3.connect(db_file)
69 c = conn.cursor() 69 initialize_db(conn)
70
71 initialize_db(c)
72 70
73 with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f: 71 with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f:
74 total_years = date.today().year + 1 - YEAR_START 72 total_years = date.today().year + 1 - YEAR_START
@@ -98,19 +96,21 @@ python do_fetch() {
98 return 96 return
99 97
100 # Compare with current db last modified date 98 # Compare with current db last modified date
101 c.execute("select DATE from META where YEAR = ?", (year,)) 99 cursor = conn.execute("select DATE from META where YEAR = ?", (year,))
102 meta = c.fetchone() 100 meta = cursor.fetchone()
101 cursor.close()
102
103 if not meta or meta[0] != last_modified: 103 if not meta or meta[0] != last_modified:
104 bb.debug(2, "Updating entries") 104 bb.debug(2, "Updating entries")
105 # Clear products table entries corresponding to current year 105 # Clear products table entries corresponding to current year
106 c.execute("delete from PRODUCTS where ID like ?", ('CVE-%d%%' % year,)) 106 conn.execute("delete from PRODUCTS where ID like ?", ('CVE-%d%%' % year,)).close()
107 107
108 # Update db with current year json file 108 # Update db with current year json file
109 try: 109 try:
110 response = urllib.request.urlopen(json_url) 110 response = urllib.request.urlopen(json_url)
111 if response: 111 if response:
112 update_db(c, gzip.decompress(response.read()).decode('utf-8')) 112 update_db(conn, gzip.decompress(response.read()).decode('utf-8'))
113 c.execute("insert or replace into META values (?, ?)", [year, last_modified]) 113 conn.execute("insert or replace into META values (?, ?)", [year, last_modified]).close()
114 except urllib.error.URLError as e: 114 except urllib.error.URLError as e:
115 cve_f.write('Warning: CVE db update error, CVE data is outdated.\n\n') 115 cve_f.write('Warning: CVE db update error, CVE data is outdated.\n\n')
116 bb.warn("Cannot parse CVE data (%s), update failed" % e.reason) 116 bb.warn("Cannot parse CVE data (%s), update failed" % e.reason)
@@ -129,21 +129,26 @@ do_fetch[lockfiles] += "${CVE_CHECK_DB_FILE_LOCK}"
129do_fetch[file-checksums] = "" 129do_fetch[file-checksums] = ""
130do_fetch[vardeps] = "" 130do_fetch[vardeps] = ""
131 131
132def initialize_db(c): 132def initialize_db(conn):
133 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)") 133 with conn:
134 c = conn.cursor()
135
136 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)")
137
138 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \
139 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)")
134 140
135 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \ 141 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \
136 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)") 142 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \
143 VERSION_END TEXT, OPERATOR_END TEXT)")
144 c.execute("CREATE INDEX IF NOT EXISTS PRODUCT_ID_IDX on PRODUCTS(ID);")
137 145
138 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \ 146 c.close()
139 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \
140 VERSION_END TEXT, OPERATOR_END TEXT)")
141 c.execute("CREATE INDEX IF NOT EXISTS PRODUCT_ID_IDX on PRODUCTS(ID);")
142 147
143def parse_node_and_insert(c, node, cveId): 148def parse_node_and_insert(conn, node, cveId):
144 # Parse children node if needed 149 # Parse children node if needed
145 for child in node.get('children', ()): 150 for child in node.get('children', ()):
146 parse_node_and_insert(c, child, cveId) 151 parse_node_and_insert(conn, child, cveId)
147 152
148 def cpe_generator(): 153 def cpe_generator():
149 for cpe in node.get('cpe_match', ()): 154 for cpe in node.get('cpe_match', ()):
@@ -200,9 +205,9 @@ def parse_node_and_insert(c, node, cveId):
200 # Save processing by representing as -. 205 # Save processing by representing as -.
201 yield [cveId, vendor, product, '-', '', '', ''] 206 yield [cveId, vendor, product, '-', '', '', '']
202 207
203 c.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator()) 208 conn.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator()).close()
204 209
205def update_db(c, jsondata): 210def update_db(conn, jsondata):
206 import json 211 import json
207 root = json.loads(jsondata) 212 root = json.loads(jsondata)
208 213
@@ -226,12 +231,12 @@ def update_db(c, jsondata):
226 accessVector = accessVector or "UNKNOWN" 231 accessVector = accessVector or "UNKNOWN"
227 cvssv3 = 0.0 232 cvssv3 = 0.0
228 233
229 c.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)", 234 conn.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)",
230 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]) 235 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]).close()
231 236
232 configurations = elt['configurations']['nodes'] 237 configurations = elt['configurations']['nodes']
233 for config in configurations: 238 for config in configurations:
234 parse_node_and_insert(c, config, cveId) 239 parse_node_and_insert(conn, config, cveId)
235 240
236 241
237do_fetch[nostamp] = "1" 242do_fetch[nostamp] = "1"