cvetriager: bin/ script
Created new bin/ script to tie all the cvetriager modules together.
This is currently being tested by CVEs picked from
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=linux+kernel. Includes
small modification to the cl generator.
BUG=chromium:1093363
TEST=python setup.py test
Change-Id: I18b2ec99d49ee4d6ebc9dd3f1f2c273c8b9a83a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2301894
Commit-Queue: Wanda Mora <morawand@chromium.org>
Tested-by: Wanda Mora <morawand@chromium.org>
Reviewed-by: Zubin Mithra <zsm@chromium.org>
diff --git a/contrib/cvetriager/bin/triage b/contrib/cvetriager/bin/triage
new file mode 100644
index 0000000..8c17eeb
--- /dev/null
+++ b/contrib/cvetriager/bin/triage
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tool that triages a given CVE."""
+
+import argparse
+import logging
+import sys
+import os
+
+from cvelib import logutils, patchapplier, contextgenerator, clgenerator, webscraper, common
+
+
+KERNELS = ['v5.4', 'v4.19', 'v4.14', 'v4.4', 'v3.18', 'v3.14', 'v3.10', 'v3.8']
+ENV_VARS = ['CHROMIUMOS_KERNEL', 'LINUX', 'STABLE', 'STABLE_RC']
+
+
+def get_parser():
+ """Returns an ArgumentParser instance."""
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('cve_number', type=str, help='CVE number to be triaged.')
+ parser.add_argument('--bug', type=str, required=True, help='BUG id to be used.')
+ parser.add_argument('--debug', help='Display debug messages.', action='store_true')
+ parser.add_argument('-rc', '--relevant_commit', help='Display commits referring to CVE fix.',
+ action='store_true')
+ parser.add_argument('--pull', help='Update kernel repositories.', action='store_true')
+ return parser
+
+
+def main(argv):
+ """Main."""
+ logger = logutils.setuplogging(logging.INFO, 'triage')
+ parser = get_parser()
+ opts = parser.parse_args(argv)
+ cve_num = opts.cve_number
+
+ for env in ENV_VARS:
+ if not os.getenv(env):
+ logger.error(f'${env} not set in virtual environment.')
+ return 1
+
+ patches = {}
+ loglvl = logging.INFO
+
+ if opts.debug:
+ loglvl = logging.DEBUG
+
+ # Change log levels.
+ modules = [webscraper, patchapplier, clgenerator]
+ for m in modules:
+ m.LOGGER.setLevel(loglvl)
+
+ # Allows pull command to execute on each branch.
+ if opts.pull:
+ common.DO_PULL = True
+
+ logger.info('Searching for possible fixes.')
+ commits = webscraper.find_relevant_commits(cve_num)
+
+ if len(commits) == 0:
+ logger.error('No commits found.')
+ return 1
+
+ for commit in commits:
+ logger.info(f'Generating context for {commit}')
+ cg = contextgenerator.ContextGenerator(KERNELS, opts.relevant_commit, loglvl)
+ cg.generate_context(commit)
+ patches[commit] = cg.kernels
+
+ for commit in commits:
+ logger.info(f'Trying to apply patch: {commit}')
+ kernels = patchapplier.apply_patch(commit, opts.bug, patches[commit])
+
+ patched_kernels = []
+
+ # Displays status of kernels after attempting to patch each one.
+ for kern in KERNELS:
+ cros_branch = common.get_cros_branch(kern)
+ if kern not in patches[commit]:
+ logger.info(f'{cros_branch}: FIXED')
+ else:
+ if kernels[kern]:
+ patched_kernels.append(kern)
+ logger.info(f'{cros_branch}: MISSING, applies cleanly')
+ else:
+ logger.info(f'{cros_branch}: MISSING, conflict')
+
+ if len(patched_kernels) != 0:
+ logger.info(f'Generating CLs for {commit}')
+ clgenerator.create_cls(opts.bug, patched_kernels)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/contrib/cvetriager/cvelib/clgenerator.py b/contrib/cvetriager/cvelib/clgenerator.py
index fa15a20..e75a33c 100644
--- a/contrib/cvetriager/cvelib/clgenerator.py
+++ b/contrib/cvetriager/cvelib/clgenerator.py
@@ -49,9 +49,10 @@
def do_push(push_cmd, kernel, kernel_path):
"""Pushes to branch."""
try:
- output = subprocess.check_output(push_cmd, stderr=subprocess.DEVNULL, cwd=kernel_path)
- except:
- raise CLGeneratorException(f'Push failed for {kernel}')
+ output = subprocess.check_output(push_cmd.split(' '), stderr=subprocess.DEVNULL,
+ cwd=kernel_path)
+ except subprocess.CalledProcessError:
+ raise CLGeneratorException(f'{kernel} repository needs to be refreshed before pushing.')
return output
diff --git a/contrib/cvetriager/setup.py b/contrib/cvetriager/setup.py
index cd8fdd5..13714b4 100644
--- a/contrib/cvetriager/setup.py
+++ b/contrib/cvetriager/setup.py
@@ -16,6 +16,12 @@
license='BSD-Google',
packages=['cvelib'],
zip_safe=False,
- install_requires=['bs4', 'requests'],
+ install_requires=[
+ 'bs4',
+ 'requests'
+ ],
test_suite='tests',
+ scripts=[
+ 'bin/triage'
+ ],
)