[OE-core] [PATCH 3/3] cve-check.bbclass: Add class

Burton, Ross ross.burton at intel.com
Mon Feb 29 14:50:39 UTC 2016


On 24 February 2016 at 15:27, <mariano.lopez at linux.intel.com> wrote:

> +# Whitelist for packages (PN)
> +cve_check_pn_whitelist () {
> +    glibc-locale
> +}


Why is this a shell function?  CVE_CHECK_PN_WHITELIST = "glibc-locale"
please.

+# Whitelist for CVE and version of package
> +python cve_check_cve_whitelist () {
> +    {"CVE-2014-2524": ("6.3",), \
> +    }
> +}


Why is this a Python function?  Make it a bare string with implied
formatting and it can be extended from outside this class, where as this
can't.


> +addtask cve_check before do_build
>

If you're expecting to look at the sources, you'll want to be after
do_fetch too.


> +do_cve_check[depends] = "cve-check-tool-native:do_populate_cve_db"
>


And cve-check-tool-native:do_populate_sysroot.


> +def get_patches_cves(d):
> +    """
> +    Get patches that solve CVEs using the "CVE: " tag.
> +    """
> +
> +    import re
> +
> +    pn = d.getVar("PN", True)
> +    cve_match = re.compile("CVE:( CVE\-\d+\-\d+)+")
>

How does this work as the backslashes are escaping the - and d and d?  Use
r"" strings.

+    patched_cves = set()
> +    for url in src_patches(d):
> +        patch_file = bb.fetch.decodeurl(url)[2]
> +        with open(patch_file, "r") as f:
> +            patch_text = f.read()
> +
> +        # Search for the "CVE: " line
> +        match = cve_match.search(patch_text)
> +        if match:
> +            # Get only the CVEs without the "CVE: " tag
> +            cves = patch_text[match.start()+5:match.end()]
> +            for cve in cves.split():
> +                patched_cves.add(cve)
>
>
Breaks for patches such as this in glibc:

meta/recipes-core/glibc/glibc/CVE-2015-9761_1.patch:CVE: CVE-2015-9761
patch #1

I'd probably look for a line that starts with "CVE:" and the use re.findall
to find all strings matching r"CVE-\d{4}-\d+"


> +    # It is needed to export the proxies to download the database using
> HTTP
> +    export_proxies(d)
>

The database has already been downloaded hasn't it?


> +    # Write the faux CSV file to be used with cve-check-tool
> +    fd, faux = tempfile.mkstemp(prefix="cve-faux-")
> +    with os.fdopen(fd, "w") as f:
> +        f.write("%s,%s,%s," % (bpn, pv, cves))
>
>
Put this inside the try incase the write fails so the file will still be
deleted.


> +    cmd += " %s" % faux
> +    try:
> +        popen = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
> stderr=subprocess.PIPE)
> +        output, error = popen.communicate()
>

Don't use the low-level function, the higher level helpers are clearer.

Always write cmd as a list unless you *need* the shell.

try:
    subprocess.check_output(cmd, stderr=subprocess.STDOUT)
except CommandCalledException as e:
    bb.warn("Couldn't check for CVEs: %s (output %s)" % (e, e.output))

+def get_cve_info(d, cves):
> +    """
> +    Get CVE information from the database used by cve-check-tool.
> +    """
> +
> +    try:
> +        import sqlite3
> +    except ImportError:
> +        from pysqlite2 import dbapi2 as sqlite3
>

Isn't the output from cve-check-tool good enough?  Would it be nicer to
extend the log instead of assuming that the database format won't ever
change?

+def cve_write_data(d, patched, unpatched, cve_data):
> +    """
> +    Write CVE information in WORKDIR; and to CVE_CHECK_DIR, and
> +    CVE manifest if enabled.
> +    """
> +
> +    from bb.utils import mkdirhier
> +
> +    cve_file = d.getVar("CVE_CHECK_LOCAL_FILE", True)
> +    nvd_link = "https://web.nvd.nist.gov/view/vuln/detail?vulnId="
> +    write_string = ""
> +    mkdirhier(d.getVar("CVE_CHECK_LOCAL_DIR", True))
> +
> +    for cve in sorted(cve_data):
> +        write_string += "PACKAGE NAME: %s\n" % d.getVar("PN", True)
> +        write_string += "PACKAGE VERSION: %s\n" % d.getVar("PV", True)
> +        write_string += "CVE: %s\n" % cve
> +        if cve in patched:
> +            write_string += "CVE STATUS: Patched\n"
> +        else:
> +            write_string += "CVE STATUS: Unpatched\n"
> +            bb.warn("Found unpatched CVE, for more information check %s"
> % cve_file)
> +        write_string += "CVE SUMMARY: %s\n" % cve_data[cve]["summary"]
> +        write_string += "CVSS v2 BASE SCORE: %s\n" %
> cve_data[cve]["score"]
> +        write_string += "VECTOR: %s\n" % cve_data[cve]["vector"]
> +        write_string += "MORE INFORMATION: %s%s\n\n" % (nvd_link, cve)
> +
> +    with open(cve_file, "w") as f:
> +        f.write(write_string)
>

Just write to the file instead of to a temporary string.

Ross
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openembedded.org/pipermail/openembedded-core/attachments/20160229/662101f9/attachment-0002.html>


More information about the Openembedded-core mailing list