[Git][cip-project/cip-kernel/cip-kernel-sec][master] 2 commits: report_affected: add support for reporting on tags


Agustin Benito Bethencourt
 

Ben Hutchings pushed to branch master at cip-project / cip-kernel / cip-kernel-sec

Commits:

  • 40329eb5
    by Daniel Sangorrin at 2019-07-17T17:30:41Z
    report_affected: add support for reporting on tags
    
    Reporting on tags is useful for product engineers that
    have shipped a kernel with a specific tag and need to know
    which issues affect their product after some time.
    
    Examples:
    $ ./scripts/report_affected.py v4.4 v4.4.107 v4.4.181-cip33
    $ cd ../kernel
    $ git tag myproduct-v1 0f13d9b4d0efa9e87381717c113df57718bc92d6
    $ cd ../cip-kernel-sec
    $ ./scripts/report_affected.py linux-4.19.y-cip:myproduct-v1 v4.19.50-cip3
    
    Signed-off-by: Daniel Sangorrin <daniel.sangorrin@...>
    Signed-off-by: Ben Hutchings <ben.hutchings@...>
    
  • d202dc5b
    by Daniel Sangorrin at 2019-07-17T17:30:41Z
    report_affected: add show-description option
    
    Rather than looking up each issue file, I would like
    to have an overview of what each CVE ID means.
    
    Example:
    $ ./scripts/report_affected.py --show-description linux-4.4.y-cip
    
    Signed-off-by: Daniel Sangorrin <daniel.sangorrin@...>
    Signed-off-by: Ben Hutchings <ben.hutchings@...>
    

4 changed files:

Changes:

  • README.md
    ... ... @@ -41,7 +41,8 @@ current or previous year or that are already tracked here.
    41 41
     stable and other configured branches, by reading the git commit logs.
    
    42 42
     
    
    43 43
     * `scripts/report_affected.py` - report which issues affect the
    
    44
    -specified branches, or all active branches.
    
    44
    +specified branches, or all active branches. You can use --show-description
    
    45
    +to obtain a short description for each CVE ID.
    
    45 46
     
    
    46 47
     * `scripts/validate.py` - validate all issue files against the
    
    47 48
     schema.
    
    ... ... @@ -72,6 +73,7 @@ keys:
    72 73
     * `base_ver`: Stable version that the branch is based on, e.g.
    
    73 74
       "4.4". This needs to be quoted so that it's a string not a
    
    74 75
       number.
    
    76
    +* `tag_regexp`: A regular expression that matches tags on a branch.
    
    75 77
     
    
    76 78
     ### Remotes
    
    77 79
     
    

  • conf/branches.yml
    ... ... @@ -2,7 +2,9 @@
    2 2
       base_ver: "4.4"
    
    3 3
       git_remote: cip
    
    4 4
       git_name: linux-4.4.y-cip
    
    5
    +  tag_regexp: '^v4\.4\.\d+-cip\d+$'
    
    5 6
     - short_name: linux-4.19.y-cip
    
    6 7
       base_ver: "4.19"
    
    7 8
       git_remote: cip
    
    8 9
       git_name: linux-4.19.y-cip
    
    10
    +  tag_regexp: '^v4\.19\.\d+-cip\d+$'

  • scripts/kernel_sec/branch.py
    ... ... @@ -23,11 +23,13 @@ from . import version
    23 23
     
    
    24 24
     def get_base_ver_stable_branch(base_ver):
    
    25 25
         branch_name = 'linux-%s.y' % base_ver
    
    26
    +    esc_base_ver = re.escape(base_ver)
    
    26 27
         return {
    
    27 28
             'short_name': branch_name,
    
    28 29
             'git_remote': 'stable',
    
    29 30
             'git_name': branch_name,
    
    30
    -        'base_ver': base_ver
    
    31
    +        'base_ver': base_ver,
    
    32
    +        'tag_regexp' : r'(^v%s$|^v%s\.\d+$)' % (esc_base_ver, esc_base_ver)
    
    31 33
             }
    
    32 34
     
    
    33 35
     
    
    ... ... @@ -141,7 +143,7 @@ def get_sort_key(branch):
    141 143
         return version.get_sort_key(base_ver)
    
    142 144
     
    
    143 145
     
    
    144
    -def _get_commits(git_repo, end, start=None):
    
    146
    +def iter_rev_list(git_repo, end, start=None):
    
    145 147
         if start:
    
    146 148
             list_expr = '%s..%s' % (start, end)
    
    147 149
         else:
    
    ... ... @@ -170,7 +172,7 @@ class CommitBranchMap:
    170 172
                                      branch['git_name'])
    
    171 173
                 else:
    
    172 174
                     end = 'v' + branch['base_ver']
    
    173
    -            for commit in _get_commits(git_repo, end, start):
    
    175
    +            for commit in iter_rev_list(git_repo, end, start):
    
    174 176
                     self._commit_sort_key[commit] \
    
    175 177
                         = self._branch_sort_key[branch_name]
    
    176 178
                 start = end
    

  • scripts/report_affected.py
    ... ... @@ -9,28 +9,53 @@
    9 9
     # Report issues affecting each stable branch.
    
    10 10
     
    
    11 11
     import argparse
    
    12
    +import copy
    
    12 13
     import subprocess
    
    14
    +import re
    
    13 15
     
    
    14 16
     import kernel_sec.branch
    
    15 17
     import kernel_sec.issue
    
    16 18
     import kernel_sec.version
    
    17 19
     
    
    18 20
     
    
    19
    -def main(git_repo, remotes,
    
    20
    -         only_fixed_upstream, include_ignored, *branch_names):
    
    21
    +def main(git_repo, remotes, only_fixed_upstream,
    
    22
    +         include_ignored, show_description, *branch_names):
    
    21 23
         live_branches = kernel_sec.branch.get_live_branches()
    
    22 24
         if branch_names:
    
    23 25
             branches = []
    
    24 26
             for branch_name in branch_names:
    
    27
    +            tag = None
    
    25 28
                 if branch_name[0].isdigit():
    
    26 29
                     # 4.4 is mapped to linux-4.4.y
    
    27 30
                     name = 'linux-%s.y' % branch_name
    
    31
    +            elif branch_name[0] == 'v':
    
    32
    +                # an official tag, e.g. v4.4.92-cip11
    
    33
    +                # infer branch from tag (regexp's must be specific)
    
    34
    +                for branch in live_branches:
    
    35
    +                    if 'tag_regexp' not in branch:
    
    36
    +                        # no tag_regexp defined, or mainline
    
    37
    +                        continue
    
    38
    +
    
    39
    +                    # predefined in branches.yml or a stable branch
    
    40
    +                    if re.match(branch['tag_regexp'], branch_name):
    
    41
    +                        tag = branch_name
    
    42
    +                        name = branch['short_name']
    
    43
    +                        break
    
    44
    +                else:
    
    45
    +                    raise ValueError('Failed to match tag %r' % branch_name)
    
    46
    +            elif ':' in branch_name:
    
    47
    +                # a possibly custom tag, e.g. linux-4.19.y-cip:myproduct-v1
    
    48
    +                name, tag = branch_name.split(':', 1)
    
    28 49
                 else:
    
    29 50
                     name = branch_name
    
    30 51
     
    
    31 52
                 for branch in live_branches:
    
    32 53
                     if branch['short_name'] == name:
    
    33
    -                    branches.append(branch)
    
    54
    +                    # there could be multiple tags for the same branch
    
    55
    +                    branch_copy = copy.deepcopy(branch)
    
    56
    +                    if tag:
    
    57
    +                        branch_copy['tag'] = tag
    
    58
    +                    branches.append(branch_copy)
    
    34 59
                         break
    
    35 60
                 else:
    
    36 61
                     msg = "Branch %s could not be found" % branch_name
    
    ... ... @@ -45,6 +70,18 @@ def main(git_repo, remotes,
    45 70
     
    
    46 71
         c_b_map = kernel_sec.branch.CommitBranchMap(git_repo, remotes, branches)
    
    47 72
     
    
    73
    +    # cache tag commits and set full_name to show the tag
    
    74
    +    tag_commits = {}
    
    75
    +    for branch in branches:
    
    76
    +        if 'tag' in branch:
    
    77
    +            start = 'v' + branch['base_ver']
    
    78
    +            end = branch['tag']
    
    79
    +            tag_commits[end] = set(
    
    80
    +                kernel_sec.branch.iter_rev_list(git_repo, end, start))
    
    81
    +            branch['full_name'] = ':'.join([branch['short_name'], end])
    
    82
    +        else:
    
    83
    +            branch['full_name'] = branch['short_name']
    
    84
    +
    
    48 85
         branch_issues = {}
    
    49 86
         issues = set(kernel_sec.issue.get_list())
    
    50 87
     
    
    ... ... @@ -65,15 +102,32 @@ def main(git_repo, remotes,
    65 102
                 if not include_ignored and ignore.get(branch_name):
    
    66 103
                     continue
    
    67 104
     
    
    105
    +            # Check if the branch is affected. If not and the issue was fixed
    
    106
    +            # on that branch, then make sure the tag contains that fix
    
    68 107
                 if kernel_sec.issue.affects_branch(
    
    69 108
                         issue, branch, c_b_map.is_commit_in_branch):
    
    70
    -                branch_issues.setdefault(branch_name, []).append(cve_id)
    
    109
    +                branch_issues.setdefault(
    
    110
    +                    branch['full_name'], []).append(cve_id)
    
    111
    +            elif 'tag' in branch and fixed:
    
    112
    +                if fixed.get(branch_name, 'never') == 'never':
    
    113
    +                    continue
    
    114
    +                for commit in fixed[branch_name]:
    
    115
    +                    if commit not in tag_commits[branch['tag']]:
    
    116
    +                        branch_issues.setdefault(
    
    117
    +                            branch['full_name'], []).append(cve_id)
    
    118
    +                        break
    
    71 119
     
    
    72 120
         for branch in branches:
    
    73
    -        branch_name = branch['short_name']
    
    74
    -        print('%s:' % branch_name,
    
    75
    -              *sorted(branch_issues.get(branch_name, []),
    
    76
    -                      key=kernel_sec.issue.get_id_sort_key))
    
    121
    +        sorted_cve_ids = sorted(
    
    122
    +            branch_issues.get(branch['full_name'], []),
    
    123
    +            key=kernel_sec.issue.get_id_sort_key)
    
    124
    +        if show_description:
    
    125
    +            print('%s:' % branch['full_name'])
    
    126
    +            for cve_id in sorted_cve_ids:
    
    127
    +                print(cve_id, '=>',
    
    128
    +                      kernel_sec.issue.load(cve_id).get('description', 'None'))
    
    129
    +        else:
    
    130
    +            print('%s:' % branch['full_name'], *sorted_cve_ids)
    
    77 131
     
    
    78 132
     
    
    79 133
     if __name__ == '__main__':
    
    ... ... @@ -102,15 +156,20 @@ if __name__ == '__main__':
    102 156
         parser.add_argument('--include-ignored',
    
    103 157
                             action='store_true',
    
    104 158
                             help='include issues that have been marked as ignored')
    
    159
    +    parser.add_argument('--show-description',
    
    160
    +                        action='store_true',
    
    161
    +                        help='show the issue description')
    
    105 162
         parser.add_argument('branches',
    
    106 163
                             nargs='*',
    
    107
    -                        help=('specific branch to report on '
    
    108
    -                              '(default: all active branches)'),
    
    109
    -                        metavar='BRANCH')
    
    164
    +                        help=('specific branch[:tag] or stable tag to '
    
    165
    +                              'report on (default: all active branches). '
    
    166
    +                              'e.g. linux-4.14.y linux-4.4.y:v4.4.107 '
    
    167
    +                              'v4.4.181-cip33 linux-4.19.y-cip:myproduct-v33'),
    
    168
    +                        metavar='[BRANCH[:TAG]|TAG]')
    
    110 169
         args = parser.parse_args()
    
    111 170
         remotes = kernel_sec.branch.get_remotes(args.remote_name,
    
    112 171
                                                 mainline=args.mainline_remote_name,
    
    113 172
                                                 stable=args.stable_remote_name)
    
    114 173
         kernel_sec.branch.check_git_repo(args.git_repo, remotes)
    
    115
    -    main(args.git_repo, remotes,
    
    116
    -         args.only_fixed_upstream, args.include_ignored, *args.branches)
    174
    +    main(args.git_repo, remotes, args.only_fixed_upstream,
    
    175
    +         args.include_ignored, args.show_description, *args.branches)

  • Join cip-dev@lists.cip-project.org to automatically receive all group messages.