From patchwork Sun Nov 24 23:50:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Armin Kuster X-Patchwork-Id: 180139 Delivered-To: patch@linaro.org Received: by 2002:a92:38d5:0:0:0:0:0 with SMTP id g82csp2443517ilf; Sun, 24 Nov 2019 15:51:51 -0800 (PST) X-Google-Smtp-Source: APXvYqw29Q8jPdAfz0SSHuJPnwsMjmsDEgqiv8lYILKZUQSGkYX9snt2g7w/TwIQdi6IUQZCMPxA X-Received: by 2002:a17:90a:c2:: with SMTP id v2mr34777215pjd.19.1574639511679; Sun, 24 Nov 2019 15:51:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574639511; cv=none; d=google.com; s=arc-20160816; b=aj3RObmwLyGDk4pdySnKtKEy3S8Vk4CJWBdDGF15l/2goRuzvAA587Kb21aUBmDodX hcAUlUhnVvYNo7q+JxJXCqyMR1zVnXX2AmetsomBg4w+yfSWua9IdqO030XAEouutKzl bnWH95XW7npqiE8s5ybshYnp3pyGP4LuOeeC427n1uZKMyCvaQAqtITbTZZLPA7p9e9f Fv8Kug7Efb5hZKyZ2c23HDlwC28ODePert/GhNqR/vwNnxYS9vKKTBrQCGRlTlAty5vU dHuHNwL9guZ1TBsbUw9ChD+L5LH85eOAfpsSnaHKeAfmhZlPXtTlUJu5R9zZ34NEAY0F RNAQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:sender:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to; bh=u1JUsLYWan8Z3e7MYkvpQUPRqj3EbRrYwOIkGOh0oqM=; b=mCdtUpnvHC0kMjSi10C3MD91lja5OtD8rDY7dNe04yTklLyqLyvUqNlK91nuIL13cX uZUGcKR/mvI8fPf/RMraTy8dtRJm9UcEbwIEO1WjkTbHyEE7x51egvc4br6aWC3cWjjN GS5DPB0tcaEVtn/+diFx1dA73Anmiu3xnux7rv6MIqfq++lXGhK2sFbNZp2aRXexGz3s g61Ydnn6PRF1oCQI4WEhOKB/jS/pMhno8EpMX/fKsW7uUgGhNOeVXtDWRyVvPWeaZ5O3 n+Aa1BEWKwi25lq1hH5PNyoRbOmE00sq+c+G8N9smGypTgmua5xQJqByxshOoT2PsQ2/ 54jg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=Av9WQ2Mu; spf=pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) smtp.mailfrom=openembedded-core-bounces@lists.openembedded.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from mail.openembedded.org (mail.openembedded.org. [140.211.169.62]) by mx.google.com with ESMTP id t2si5252287pjv.97.2019.11.24.15.51.51; Sun, 24 Nov 2019 15:51:51 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) client-ip=140.211.169.62; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=Av9WQ2Mu; spf=pass (google.com: best guess record for domain of openembedded-core-bounces@lists.openembedded.org designates 140.211.169.62 as permitted sender) smtp.mailfrom=openembedded-core-bounces@lists.openembedded.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from ec2-34-214-78-129.us-west-2.compute.amazonaws.com (localhost [127.0.0.1]) by mail.openembedded.org (Postfix) with ESMTP id DB5977FCD1; Sun, 24 Nov 2019 23:51:09 +0000 (UTC) X-Original-To: openembedded-core@lists.openembedded.org Delivered-To: openembedded-core@lists.openembedded.org Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) by mail.openembedded.org (Postfix) with ESMTP id 14F5D7FC5B for ; Sun, 24 Nov 2019 23:50:49 +0000 (UTC) Received: by mail-pl1-f169.google.com with SMTP id o8so1243876pls.5 for ; Sun, 24 Nov 2019 15:50:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=tjZEj4TEig4bdgdtgNoK9YnzbLGx27mq5OgwL25/zIQ=; b=Av9WQ2MuiiC9xMXGIrGXGXdK489lJxo6C/+jIGa0ZztfsmYCW7fZyxhwoCH/fTFCx1 71MD2zXeHnb5nGcTehfPl0iEpJmmOcPXjcyZniyCDoMA4AxiluaHXHjuXV3xCDuhma39 gLHeu/THP8Vf2bAMXl3S3U338A12HGTw3oa25VWFzCup9k6Pm+6b4AA+ZjQhusjyTyf6 8ilmJElNVONFcu2E0x4XEmT4TbWKAcQMC02q/Um8nWn1LhfZzOQkQDnAdakRH7N5zvdL Yi0azzOnolx/+Ra1bDZFV2TCWTw6lvF6AtnXcq9Ndy9Asr2tBOZE8ljZf1jCTvDmpPYV VnHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=tjZEj4TEig4bdgdtgNoK9YnzbLGx27mq5OgwL25/zIQ=; b=qw+b1gt4rIdTCbs/aiioJuofccTLf6GB0qF+H0XDeKWpGtSeETzf3XdO2plKmlMFH0 /x388PdJx3Z79wWRZBr/1/CXxvrl1Hx8oKHJyyEb+fUZ2fRlDZCPijsRaaMQtQePrpFt IRVzaKapnS93vuGAZ2Be2RE7Ia3EKWrrPOsdaQm0yd1gwnuMWpJHkhwtPbqeH4A7ylpi 2Uhvy/Fqqt6RSskdQU4zNzn+kOTX6q24DZht6a93IiwVcL/Em0Isoo+43K+kn1IVg7wU a0pXWRpNjVXxGFHZk7yq2/GYmDDyUFEMfGRG353vnGlyLk3nY6pZiO37fm5YxfGCwfjz am0g== X-Gm-Message-State: APjAAAVs+vuj8RX0GbPUSzYuMUdFpFTF0zB2jmzk74xj9EEd5YY4PqJT 8/7m70p5sGUeWkR4AhOAXG/u1PHl X-Received: by 2002:a17:90b:30ca:: with SMTP id hi10mr35331070pjb.143.1574639450998; Sun, 24 Nov 2019 15:50:50 -0800 (PST) Received: from akuster-ThinkPad-T460s.hsd1.ca.comcast.net ([2601:202:4180:a5c0:69ac:e4d2:e89f:98da]) by smtp.gmail.com with ESMTPSA id q200sm5619783pfq.87.2019.11.24.15.50.50 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 24 Nov 2019 15:50:50 -0800 (PST) From: Armin Kuster To: openembedded-core@lists.openembedded.org Date: Sun, 24 Nov 2019 15:50:13 -0800 Message-Id: <0d261e259f351b18ac52866792db04ceea382cc7.1574639349.git.akuster808@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: Subject: [OE-core] [zeus 08/35] cve-check: rewrite look to fix false negatives X-BeenThere: openembedded-core@lists.openembedded.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Patches and discussions about the oe-core layer List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: openembedded-core-bounces@lists.openembedded.org Errors-To: openembedded-core-bounces@lists.openembedded.org From: Ross Burton A previous optimisation was premature and resulted in false-negatives in the report. Rewrite the checking algorithm to first get the list of potential CVEs by vendor:product, then iterate through every matching CPE for that CVE to determine if the bounds match or not. By doing this in two stages we can know if we've checked every CPE, instead of accidentally breaking out of the scan too early. (From OE-Core rev: d61aff9e22704ad69df1f7ab0f8784f4e7cc0c69) Signed-off-by: Ross Burton Signed-off-by: Richard Purdie Signed-off-by: Anuj Mittal --- meta/classes/cve-check.bbclass | 63 +++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 29 deletions(-) -- 2.7.4 -- _______________________________________________ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass index 3326944..c1cbdbd 100644 --- a/meta/classes/cve-check.bbclass +++ b/meta/classes/cve-check.bbclass @@ -165,7 +165,6 @@ def check_cves(d, patched_cves): """ Connect to the NVD database and find unpatched cves. """ - import ast, csv, tempfile, subprocess, io from distutils.version import LooseVersion cves_unpatched = [] @@ -187,68 +186,74 @@ def check_cves(d, patched_cves): cve_whitelist = d.getVar("CVE_CHECK_WHITELIST").split() import sqlite3 - db_file = d.getVar("CVE_CHECK_DB_FILE") - conn = sqlite3.connect(db_file) + db_file = d.expand("file:${CVE_CHECK_DB_FILE}?mode=ro") + conn = sqlite3.connect(db_file, uri=True) + # For each of the known product names (e.g. curl has CPEs using curl and libcurl)... for product in products: - c = conn.cursor() if ":" in product: vendor, product = product.split(":", 1) - c.execute("SELECT * FROM PRODUCTS WHERE PRODUCT IS ? AND VENDOR IS ?", (product, vendor)) else: - c.execute("SELECT * FROM PRODUCTS WHERE PRODUCT IS ?", (product,)) + vendor = "%" - for row in c: - cve = row[0] - version_start = row[3] - operator_start = row[4] - version_end = row[5] - operator_end = row[6] + # Find all relevant CVE IDs. + for cverow in conn.execute("SELECT DISTINCT ID FROM PRODUCTS WHERE PRODUCT IS ? AND VENDOR LIKE ?", (product, vendor)): + cve = cverow[0] if cve in cve_whitelist: bb.note("%s-%s has been whitelisted for %s" % (product, pv, cve)) # TODO: this should be in the report as 'whitelisted' patched_cves.add(cve) + continue elif cve in patched_cves: bb.note("%s has been patched" % (cve)) - else: - to_append = False + continue + + vulnerable = False + for row in conn.execute("SELECT * FROM PRODUCTS WHERE ID IS ? AND PRODUCT IS ? AND VENDOR LIKE ?", (cve, product, vendor)): + (_, _, _, version_start, operator_start, version_end, operator_end) = row + #bb.debug(2, "Evaluating row " + str(row)) + if (operator_start == '=' and pv == version_start): - to_append = True + vulnerable = True else: if operator_start: try: - to_append_start = (operator_start == '>=' and LooseVersion(pv) >= LooseVersion(version_start)) - to_append_start |= (operator_start == '>' and LooseVersion(pv) > LooseVersion(version_start)) + vulnerable_start = (operator_start == '>=' and LooseVersion(pv) >= LooseVersion(version_start)) + vulnerable_start |= (operator_start == '>' and LooseVersion(pv) > LooseVersion(version_start)) except: bb.warn("%s: Failed to compare %s %s %s for %s" % (product, pv, operator_start, version_start, cve)) - to_append_start = False + vulnerable_start = False else: - to_append_start = False + vulnerable_start = False if operator_end: try: - to_append_end = (operator_end == '<=' and LooseVersion(pv) <= LooseVersion(version_end)) - to_append_end |= (operator_end == '<' and LooseVersion(pv) < LooseVersion(version_end)) + vulnerable_end = (operator_end == '<=' and LooseVersion(pv) <= LooseVersion(version_end)) + vulnerable_end |= (operator_end == '<' and LooseVersion(pv) < LooseVersion(version_end)) except: bb.warn("%s: Failed to compare %s %s %s for %s" % (product, pv, operator_end, version_end, cve)) - to_append_end = False + vulnerable_end = False else: - to_append_end = False + vulnerable_end = False if operator_start and operator_end: - to_append = to_append_start and to_append_end + vulnerable = vulnerable_start and vulnerable_end else: - to_append = to_append_start or to_append_end + vulnerable = vulnerable_start or vulnerable_end - if to_append: + if vulnerable: bb.note("%s-%s is vulnerable to %s" % (product, pv, cve)) cves_unpatched.append(cve) - else: - bb.note("%s-%s is not vulnerable to %s" % (product, pv, cve)) - patched_cves.add(cve) + break + + if not vulnerable: + bb.note("%s-%s is not vulnerable to %s" % (product, pv, cve)) + # TODO: not patched but not vulnerable + patched_cves.add(cve) + conn.close() return (list(patched_cves), cves_unpatched)