Merge ~alexmurray/ubuntu-cve-tracker:noboilerplates-3 into ubuntu-cve-tracker:master

Proposed by Alex Murray
Status: Merged
Merged at revision: 7120fd2d1eeb59d24bedb5dae0e1ab13d85b1b45
Proposed branch: ~alexmurray/ubuntu-cve-tracker:noboilerplates-3
Merge into: ubuntu-cve-tracker:master
Diff against target: 1534 lines (+505/-582)
19 files modified
README (+4/-5)
README.mozilla (+3/-2)
README.usn (+1/-1)
README.webkit (+3/-3)
scripts/active_edit (+123/-269)
scripts/add-derived-kernel (+33/-11)
scripts/add_meta_info.py (+4/-2)
scripts/boilerplate-to-json.py (+151/-0)
scripts/check-cves (+110/-220)
scripts/check-syntax (+10/-17)
scripts/check-syntax-fixup (+0/-5)
scripts/cve-mode.el (+1/-3)
scripts/cve.vim (+0/-1)
scripts/cve_lib.py (+54/-24)
scripts/dup-status-for-pkg (+1/-1)
scripts/kernel-triage-missing-break-fix (+1/-1)
scripts/release-cycle-devel-opens (+1/-1)
scripts/release-cycle-released (+1/-1)
scripts/sync-from-eol.py (+4/-15)
Reviewer Review Type Date Requested Status
Alex Murray Needs Fixing
Seth Arnold Approve
Eduardo Barretto Approve
Review via email: mp+427753@code.launchpad.net

Description of the change

This series of commits is designed to allow us to replace the boilerplate files and the package_info_overrides.json with a single package-db.json which captures the details of all these data sources. I have left out the one remaining commit which would remove these old data sources and add the new package-db.json file so that we can generate this once this is merged so that it does not conflict too much.

To test this branch you will need to generate this package-db.json as:

./scripts/boilerplate-to-json.py > meta_lists/package-db.json

Then you should be able to do CVE triage and run active_edit etc etc as normal.

The main benefit this change gives is a better way to represent this data *plus* it ensures that when say updating a CVE with a boilerplate target (e.g. active_edit -C CVE-NNNN-XXXX -p openjdk) - that the packages captured by that boilerplate (ie openjdk-10 etc) all get added to the CVE file as expected *along with all the various subprojects*. This should mean we don't have to use check-syntax-fixup so much.

To post a comment you must log in.
Revision history for this message
Steve Beattie (sbeattie) wrote :

One thing I caught in the most briefest of surface level reviews:

On Wed, Aug 03, 2022 at 07:05:15AM -0000, Alex Murray wrote:
> +# TODO - decide if we want to keep this - for now leave it out
> +
> +# also parse debian's embedded-code-copies and amalgate that into data
> +for f in ["../security-tracker/data/embedded-code-copies"]:

If you do keep this, please use the `secure_testing_path`
from the ~/.ubuntu-cve-tracker.conf config file (obtained via
cve_lib.read_config()) instead of hard-coding a relative path and
repo name when reading debian's embedded-code-copies data.

Thanks.

--
Steve Beattie
<email address hidden>

Revision history for this message
Steve Beattie (sbeattie) wrote :

Again, have not read in detail...

On Wed, Aug 03, 2022 at 07:05:15AM -0000, Alex Murray wrote:

> diff --git a/scripts/add-derived-kernel b/scripts/add-derived-kernel
> index d219586..f4c96c9 100755
> --- a/scripts/add-derived-kernel
> +++ b/scripts/add-derived-kernel
> @@ -105,6 +105,6 @@ echo "Updating status of released CVEs (ok if empty and prints help)..."
> xargs --no-run-if-empty ./scripts/mass-cve-edit -p "linux-${KERNEL}" -r "${RELEASE}" -s not-affected
>
> printf "\n\nPlease update cve_lib.py, kernel_lib.py, sis-generate-usn, cve-alert.sh, and prepare-kernel-usn.py in scripts/\n"
> -echo "Please add package description information if necessary to meta_lists/package_info_overrides.json"
> +echo "Please add package description information if necessary to meta_lists/package-db.json"
> echo "If this kernel has not been published yet, please add it to the unpublished_kernels list in check-syntax."
> echo "Also, before publishing a USN against the new kernel, ensure packages_mirror has been run"

Plesae note that one of the things the `add-derived-kernel` script does
for the new kernel being added for tracking in UCT is add it to the
boilerplate (I subsequently adjust the addition's location in the
boilerplate to try to keep them relatively organized). Is there a way
add-derived-kernel could be updated to do this under the new structure?

(Yes, there is post-hoc manual editing to be done after
add-derived-kernel does its thing, but my intent is to reduce that as
much as possible, to avoid errors.)

--
Steve Beattie
<email address hidden>

Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks for the comments @sbeattie - see https://git.launchpad.net/~alexmurray/ubuntu-cve-tracker/commit/?id=ae277c8a754f907248feff4cb0fdd39e68136f37 which updates add-derived-kernel to now update package-db.json instead of 00boilerplate.linux, plus https://git.launchpad.net/~alexmurray/ubuntu-cve-tracker/commit/?id=81ff3b0a1caa32ae8bdce9952883fecbbf076fb8 which updates boilerplate-to-json to use the configured path to the debian secure_testing repo rather than assuming it.

Revision history for this message
Alex Murray (alexmurray) wrote :

So this merge request has had no real review for almost a whole month... I would really like to get it merged so will likely just merge it next week unless anyone wants to give it a look over... TIA 🙏

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

Small fix in indentation, but the code looks good to me.
I believe you will send another PR, later when things are working in this new structure, to do the cleanup in cve_lib (load_boilerplates()) and remove the current boilerplates, right?

review: Needs Fixing
Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks @ebarretto - I have fixed the indentation in https://git.launchpad.net/~alexmurray/ubuntu-cve-tracker/commit/?id=8ba68cbe6f16231c02947e553cd568a2b6b4cd04 and have removed load_boilerplates() from cve_lib in https://git.launchpad.net/~alexmurray/ubuntu-cve-tracker/commit/?id=1ec5cbbe7d208c2104d40505111b6947de29285f

Yes, once this is merged in then I plan to actually remove the boilerplate files *and* generate the new package-db.json and commit this to UCT (plus remove the now obsolete package_info_overrides.json since it has been subsumed into package-db.json) - I just didn't add that as part of this PR to keep this smaller and easier to review, otherwise the diff would have been huge.

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

lgtm, thanks!

review: Approve
Revision history for this message
Seth Arnold (seth-arnold) wrote :

Sorry for not getting to this sooner :( I like quite a lot of it. I'd love to be rid of the boilerplates.

I've got a few comments inline.

Thanks

review: Approve
Revision history for this message
Alex Murray (alexmurray) wrote :

Thanks Seth - fixed the typo and moved the parse_embedded_code_copies() down so it was clear that is is not used currently.

Regarding wordwrap() etc - that is simply stolen from check-cves and moved into cve_lib now so that we can reuse it - so it will have the same functionality as it did before - I have not modified it.

Revision history for this message
Alex Murray (alexmurray) wrote :

I just noticed that I missed a few other scripts that still refer to the boilerplate files so they will need to be fixed up before this gets merged:

scripts/release-cycle-devel-opens
scripts/release-cycle-released
scripts/dup-status-for-pkg
scripts/sync-from-eol.py

Basically `git grep boilerplate` should return nothing when this MR is actually ready.

review: Needs Fixing
Revision history for this message
Seth Arnold (seth-arnold) wrote :

scripts/dup-status-for-pkg can probably just delete this word:
active/00boilerplate*

scripts/release-cycle-released can probably delete the paragraph.

scripts/release-cycle-devel-opens can probably just change:
active/{CVE-,00boilerplate}*
to:
active/CVE-*

scripts/sync-from-eol.py will require a lot more thinking.

Getting rid of the boilerplates looks like it'll simplify a lot :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/README b/README
index 433dde7..8817769 100644
--- a/README
+++ b/README
@@ -597,7 +597,7 @@ Stable Release Actions
597----------------------597----------------------
598When a stable release is published, the active CVEs need to be adjusted to598When a stable release is published, the active CVEs need to be adjusted to
599reflect the new stable release. e.g. when trusty was published:599reflect the new stable release. e.g. when trusty was published:
600 perl -pi -e 's/^((#?)devel_(.*))/$2trusty_$3\n$1/g' active/{CVE-,00boilerplate}*600 perl -pi -e 's/^((#?)devel_(.*))/$2trusty_$3\n$1/g' active/CVE-*
601The script tools will need to be adjusted as well. There is usually some601The script tools will need to be adjusted as well. There is usually some
602lag time between the new devel archive opening and the stable release602lag time between the new devel archive opening and the stable release
603getting published. This means that "devel" will disappear from ubuntu-table603getting published. This means that "devel" will disappear from ubuntu-table
@@ -611,7 +611,7 @@ briefly:
611611
612 scripts/cve_lib.py should have an empty 'devel_release'.612 scripts/cve_lib.py should have an empty 'devel_release'.
613613
614Move all active CVEs and boilerplates from "devel" to release state:614Move all active CVEs from "devel" to release state:
615./scripts/release-cycle-released $RELEASE615./scripts/release-cycle-released $RELEASE
616616
617617
@@ -619,7 +619,7 @@ Development Release Actions
619---------------------------619---------------------------
620Fill in releases and devel_release in ubuntu-cve-tools/scripts/cve_lib.py620Fill in releases and devel_release in ubuntu-cve-tools/scripts/cve_lib.py
621621
622Move all active CVEs and boilerplates from latest release to devel state:622Move all active CVEs from latest release to devel state:
623./scripts/release-cycle-devel-opens $LATEST_STABLE_RELEASE623./scripts/release-cycle-devel-opens $LATEST_STABLE_RELEASE
624624
625Add release to non-ports and ports section of625Add release to non-ports and ports section of
@@ -635,7 +635,6 @@ Here is how:
635635
6362. update the CVEs:6362. update the CVEs:
637$ sed -i 's/^<release>_\(.*\): \(needed\|needs\-triage\)/<release>_\1: \2 (reached end-of-life)/g' ./active/CVE-*637$ sed -i 's/^<release>_\(.*\): \(needed\|needs\-triage\)/<release>_\1: \2 (reached end-of-life)/g' ./active/CVE-*
638$ sed -i '/^<release>_\(.*\): /d' ./active/00boilerplate*
639638
6403. retire the CVEs (see 'Retiring items', above)6393. retire the CVEs (see 'Retiring items', above)
641640
@@ -678,7 +677,7 @@ New Backport Kernel
678When a new backport kernel is added, update scripts/cve_lib.py's677When a new backport kernel is added, update scripts/cve_lib.py's
679kernel_srcs and description_overrides.678kernel_srcs and description_overrides.
680679
681Then update the 00boilerplate.linux with its entry, add that entry to each680Then update the meta_lists/package-db.json with its entry, add that entry to each
682CVE with an entry for the LTS the kernel was added to, and update all the681CVE with an entry for the LTS the kernel was added to, and update all the
683statuses for the newly added kernel, based off the version it will be682statuses for the newly added kernel, based off the version it will be
684branched from. For example, to add a new kernel backported from Vivid to683branched from. For example, to add a new kernel backported from Vivid to
diff --git a/README.mozilla b/README.mozilla
index 5e06594..7c0f1f2 100644
--- a/README.mozilla
+++ b/README.mozilla
@@ -45,7 +45,7 @@ CVE Triage
45----------45----------
46CVEs in Firefox are tracked in the xulrunner source packages for builds that46CVEs in Firefox are tracked in the xulrunner source packages for builds that
47use the system xulrunner, and firefox source packages for those that use a47use the system xulrunner, and firefox source packages for those that use a
48static build. active/00boilerplate.firefox is used to capture the source48static build. meta_lists/package-db.json is used to capture the source
49package relationships when triaging CVEs for firefox (ie, you only need to49package relationships when triaging CVEs for firefox (ie, you only need to
50specify 'firefox' as the source package).50specify 'firefox' as the source package).
5151
@@ -65,6 +65,7 @@ xulrunner-1.9.2: system xul for reverese dependencies that process web content.
65firefox: Ubuntu 8.04 LTS and higher (static build of 3.6.x or higher)65firefox: Ubuntu 8.04 LTS and higher (static build of 3.6.x or higher)
6666
67Additionally, the following share a common codebase and are affected by the67Additionally, the following share a common codebase and are affected by the
68same CVE often enough that they warrant being part of the firefox boilerplate:68same CVE often enough that they warrant being part of the firefox pkgs set in
69meta_lists/package-db.json:
69seamonkey70seamonkey
70thunkerbird71thunkerbird
diff --git a/README.usn b/README.usn
index ac8156f..e5c3f58 100644
--- a/README.usn
+++ b/README.usn
@@ -30,7 +30,7 @@ versions.
30Make sure the source package description was properly set for every affected30Make sure the source package description was properly set for every affected
31release (i.e. the value for the usn.py --source-description argument in the31release (i.e. the value for the usn.py --source-description argument in the
32generated usn shell script is set). If it was not automatically populated, make32generated usn shell script is set). If it was not automatically populated, make
33sure the source package is present in $UCT/meta_list/package_info_overrides.json33sure the source package is present in $UCT/meta_list/package-db.json
34and add it if it is not.34and add it if it is not.
3535
36** CVEs references36** CVEs references
diff --git a/README.webkit b/README.webkit
index 187d619..a52bf88 100644
--- a/README.webkit
+++ b/README.webkit
@@ -75,7 +75,7 @@ chromium-browser
7575
76This package contains a fork of the WebKit code base (aka 'Blink'). It is76This package contains a fork of the WebKit code base (aka 'Blink'). It is
77maintained separately by Google and is tracked in the 'chromium-browser'77maintained separately by Google and is tracked in the 'chromium-browser'
78boilerplate.78entry in meta_lists/package-db.json.
7979
80oxide80oxide
81-----81-----
@@ -83,11 +83,11 @@ oxide
83Oxide is bindings for the chromium content api and therefore contains a fork83Oxide is bindings for the chromium content api and therefore contains a fork
84of the webkit code base (aka, 'Blink'). The chromium content api is maintained84of the webkit code base (aka, 'Blink'). The chromium content api is maintained
85separately by Google and Oxide is maintained by Canonical. Oxide is tracked in85separately by Google and Oxide is maintained by Canonical. Oxide is tracked in
86the 'chromium-browser' boilerplate.86the 'chromium-browser' entry in meta_lists/package-db.json.
8787
88CVE Triage88CVE Triage
89----------89----------
90active/00boilerplate.webkit is used to capture the source package relationships90meta_lists/package-db.json is used to capture the source package relationships
91when triaging CVEs for webkit (ie, you only need to specify 'webkit' as the91when triaging CVEs for webkit (ie, you only need to specify 'webkit' as the
92source package).92source package).
9393
diff --git a/scripts/active_edit b/scripts/active_edit
index a85f279..482446c 100755
--- a/scripts/active_edit
+++ b/scripts/active_edit
@@ -10,9 +10,9 @@
1010
11import optparse11import optparse
12import os12import os
13import pathlib
13import re14import re
14import sys15import sys
15import time
1616
17import cve_lib17import cve_lib
18import source_map18import source_map
@@ -21,7 +21,6 @@ releases = ['upstream'] + cve_lib.all_releases
2121
22max_file_size = 10 * 1024 * 1024 # 10MB22max_file_size = 10 * 1024 * 1024 # 10MB
23cvedir = cve_lib.active_dir23cvedir = cve_lib.active_dir
24boilerplates = cvedir
2524
26parser = optparse.OptionParser()25parser = optparse.OptionParser()
27parser.add_option("-p", "--package", dest="pkgs", help="Package name and optional version where package is fixed (with optional Ubuntu release and version in that release)", metavar="NAME[,VERSION[,RELEASE,RELEASE_VERSION]]", action="append")26parser.add_option("-p", "--package", dest="pkgs", help="Package name and optional version where package is fixed (with optional Ubuntu release and version in that release)", metavar="NAME[,VERSION[,RELEASE,RELEASE_VERSION]]", action="append")
@@ -30,7 +29,8 @@ parser.add_option("-r", "--reference-url", dest="ref_urls", help="URL references
30parser.add_option("-c", "--cve", dest="cve", help="CVE entry", metavar="CVE-YYYY-NNNN")29parser.add_option("-c", "--cve", dest="cve", help="CVE entry", metavar="CVE-YYYY-NNNN")
31parser.add_option("-e", "--embargoed", dest="embargoed", help="This is an embargoed entry", action="store_true")30parser.add_option("-e", "--embargoed", dest="embargoed", help="This is an embargoed entry", action="store_true")
32parser.add_option("-y", "--yes", dest="autoconfirm", help="Do not ask for confirmation", action="store_true")31parser.add_option("-y", "--yes", dest="autoconfirm", help="Do not ask for confirmation", action="store_true")
33parser.add_option("-P", "--public", help="Record date the CVE went public", metavar="YYYY-MM-DD")32parser.add_option("-P", "--public", dest="public_date", help="Record date the CVE went public", metavar="YYYY-MM-DD")
33parser.add_option("--priority", help="Record a priority for the CVE", default=None)
34parser.add_option("-C", "--cvss", help="CVSS3.1 rating", metavar="CVSS:3.1/AV:_/AC:_/PR:_/UI:_/S:_/C:_/I:_/A:_")34parser.add_option("-C", "--cvss", help="CVSS3.1 rating", metavar="CVSS:3.1/AV:_/AC:_/PR:_/UI:_/S:_/C:_/I:_/A:_")
35(options, args) = parser.parse_args()35(options, args) = parser.parse_args()
3636
@@ -70,6 +70,7 @@ def create_or_update_external_subproject_cves(cve, pkgname):
70 continue70 continue
71 affected_releases.append(release)71 affected_releases.append(release)
7272
73 ans = "y"
73 if not options.autoconfirm:74 if not options.autoconfirm:
74 print("\n")75 print("\n")
75 for release in affected_releases:76 for release in affected_releases:
@@ -101,245 +102,130 @@ def release_wants_dne(release):
101 _, product, _, _ = cve_lib.get_subproject_details(release)102 _, product, _, _ = cve_lib.get_subproject_details(release)
102 return product != None and product == cve_lib.PRODUCT_UBUNTU103 return product != None and product == cve_lib.PRODUCT_UBUNTU
103104
104def update_cve(cve, pkgname, fixed_in=None, fixed_in_release=None, fixed_in_release_version=None):
105 '''Update an existing CVE file'''
106 with open(os.path.join(cvedir, cve), "r") as f:
107 lines = f.read(max_file_size).split('\n')
108
109 skipped = []
110 added_lines = ""
111
112 tmp_releases = get_releases(pkgname)
113
114 # If we are using 00boilerplate.<pkgname> and the package is DNE on all
115 # current releases, then don't add the the stanza for this release. This
116 # allows us to use generic boilerplate names like 00boilerplate.gnutls or
117 # 00boilerplate.openjdk without adding useless extra stanzas.
118 # TODO: this still doesn't handle adding the contents of the boilerplate
119 # to an existing CVE (ie, ./scripts/sctive_edit -p openjdk -c CVE-YYYY-NNNN
120 # where CVE-YYYY-NNNN already exists)
121 if os.path.exists(os.path.join(boilerplates, '00boilerplate.%s' % pkgname)):
122 pkg_exists_somewhere = False
123 for r in tmp_releases:
124 if r == 'upstream' or (r in cve_lib.eol_releases \
125 and not cve_lib.is_active_esm_release(r)):
126 continue
127 if pkg_in_rel(pkgname,r):
128 pkg_exists_somewhere = True
129 break
130 if not pkg_exists_somewhere:
131 print("skipping '" + pkgname + "' (DNE on all current releases)\n", file=sys.stderr)
132 return
133
134 for line in lines:
135 for r in tmp_releases:
136 if r == cve_lib.devel_release or r == '':
137 r = 'devel'
138 if not re.match(r'^' + r + ".*:", line):
139 continue
140 tmp = line.split(':')
141 match = "%s_%s" % (r, pkgname)
142 if match == tmp[0]:
143 skipped.append(r)
144
145 if len(skipped) == 0:
146 added_lines += '\nPatches_' + pkgname + ':\n'
147
148 higher_not_affected = False
149 for release in tmp_releases:
150 # don't add any external releases
151 if release in cve_lib.external_releases:
152 continue
153
154 r = release
155 if r == cve_lib.devel_release or r == '':
156 r = 'devel'
157
158 if r in skipped:
159 print("skipping '" + pkgname + "' for " + r + " (already included)\n", file=sys.stderr)
160 else:
161 # skip eol_releases releases without esm support
162 if r in cve_lib.eol_releases \
163 and (not cve_lib.is_active_esm_release(r) or r == 'precise'):
164 continue
165 state = "needs-triage"
166 if not pkg_in_rel(pkgname, release):
167 # package doesn't exist in this release - see if it wants a
168 # DNE entry
169 if release_wants_dne(release):
170 state = "DNE"
171 else:
172 continue
173 elif cve_lib.is_active_esm_release(r):
174 state = "ignored (out of standard support)"
175 elif r == 'upstream' and fixed_in is not None:
176 state = "released (%s)" % fixed_in
177 elif fixed_in_release_version and r == fixed_in_release:
178 state = "not-affected (%s)" % fixed_in_release_version
179 higher_not_affected = True
180 elif higher_not_affected:
181 state = "not-affected"
182 added_lines += '%s_%s: %s\n' % (r, pkgname, state)
183
184 if len(releases) == len(skipped):
185 print("\nNothing to add!\n")
186 return
187
188 if not options.autoconfirm:
189 print("\n" + added_lines)
190 print("\nAppend the above to " + os.path.join(cvedir, cve) + " (y|N)? ")
191 ans = sys.stdin.readline().lower()
192 print("\n")
193 else:
194 ans = "y"
195105
196 if ans.startswith("y"):106def create_or_update_cve(cve, packages, priority=None, bug_urls=None, ref_urls=None, public_date=None, desc=None, cvss=None):
197 file = open(os.path.join(cvedir, cve), "a")107
198 file.write(added_lines)108 pkgs = []
199 file.close()109 fixed = {}
110 # parse optional fixed_in release and version from package name
111 for p in packages:
112 tmp_p = p.split(',')
113 pkg = tmp_p[0]
114 pkgs.append(pkg)
115 fixed[pkg] = tmp_p[1:]
116
117 update = False
118 try:
119 dst = cve_lib.find_cve(cve)
120 update = True
121 except ValueError:
122 dst = os.path.join(pathlib.Path().parent.resolve(), "active", cve)
123
124 # collect notes from pkg_db and add any extra pkgs from pkg_db as well
125 notes = []
126 for p in pkgs:
127 if p in pkg_db:
128 notes = notes + pkg_db[p]["notes"]
129 pkgs = pkgs + list(pkg_db[p]["pkgs"].keys())
130
131 # normalise the list of packages
132 pkgs = sorted(list(set(pkgs)))
133
134 # remove any packages which don't actually exist in any release
135 for p in pkgs:
136 keep = False
137 for r in source.keys():
138 keep |= p in source[r]
139 if not keep:
140 pkgs.remove(p)
141
142 if update:
143 mode = "a"
200 else:144 else:
201 print("Aborted\n")145 mode = "w"
202146 with open(dst, mode, encoding="utf-8") as fp:
203def create_cve(cve, pkgname, fixed_in=None, fixed_in_release=None, fixed_in_release_version=None):147 if not update:
204 '''Create a new CVE file'''148 print('Candidate: %s' % (cve), file=fp)
205 src = os.path.join(boilerplates, '00boilerplate')149 print('PublicDate: %s' % (public_date if public_date else "unknown"), file=fp)
206 if os.path.exists(src + "." + pkgname):150 print('References:\n https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s' % (cve), file=fp)
207 src = src + "." + pkgname151 for url in (ref_urls if ref_urls else []):
208 boiler = open(src, "r")152 print(" %s" % url, file=fp)
209 lines = boiler.read(max_file_size).splitlines()153 print('Description:', file=fp)
210 boiler.close()154 for desc_line in (cve_lib.wrap_text(desc).split('\n') if desc else []):
211155 print(" %s" % (desc_line), file=fp)
212 cand_pat = re.compile(r'^Candidate:')156 print('Ubuntu-Description:', file=fp)
213 ref_pat = re.compile(r'^References:')157 print('Notes:', file=fp)
214 bugs_pat = re.compile(r'^Bugs:')158 for note in notes:
215 cvss_pat = re.compile(r'^CVSS:')159 for note_line in cve_lib.wrap_text(note[1], 75 - len(note[0]) - 2).split('\n'):
216 pkg_pat = re.compile(r'^#?[a-z/\-]+_(PKG|%s):' % pkgname)160 print(" %s> %s" % (note[0], note_line), file=fp)
217 patch_pat = re.compile(r'^#?Patches_(PKG|%s):' % pkgname)161 print('Mitigation:', file=fp)
218162 print('Bugs:', file=fp)
219 tmp_releases = get_releases(pkgname)163 for url in (bug_urls if bug_urls else []):
220 added = set()164 print(" %s" % url, file=fp)
221165 print('Priority: %s' % (priority if priority else "untriaged"), file=fp)
222 contents = ""166 print('Discovered-by:', file=fp)
223 higher_not_affected = False167 print('Assigned-to:', file=fp)
224 for line in lines:168 print('CVSS:', file=fp)
225 if (cand_pat.search(line)):169 for entry in (cvss if cvss else []):
226 contents += line + os.path.basename(cve) + '\n'170 src, cvss = entry
227 elif line.startswith('PublicDate:'):171 print(' %s: %s' % (src, cvss), file=fp)
228 if options.embargoed:172
229 if options.public:173 # add package info from pkg_db
230 # use public date as CRD174 for p in pkgs:
231 contents += "CRD: %s\n" % options.public175 print('', file=fp)
232 else:176 print('Patches_%s:' % p, file=fp)
233 contents += "CRD: <TBD>\n"177 # find which releases p exists in
234 if options.public:178 higher_not_affected = False
235 contents += "PublicDate: %s\n" % options.public179 fixed_in = None
236 else:180 fixed_in_release = None
237 # default to today-- this will be refreshed by check-cves181 fixed_in_release_version = None
238 contents += "PublicDate: %s\n" % time.strftime("%Y-%m-%d", time.gmtime())182 if p in fixed and len(fixed[p]) > 0:
239 elif (cvss_pat.search(line)):183 fixed_in = fixed[p][0]
240 if options.cvss:184 if len(fixed[p]) > 1:
241 contents += 'CVSS: ' + options.cvss + '\n'185 fixed_in_release = fixed[p][1]
242 else:186 if len(fixed[p]) > 2:
243 contents += 'CVSS:\n'187 fixed_in_release_version = fixed[p][2]
244 elif (patch_pat.search(line)):188 for rel in ['upstream'] + list(source.keys()):
245 contents += '\nPatches_' + pkgname + ':\n'189 # determine default state but override this if pkg_db has a
246 elif (pkg_pat.search(line)):190 # better one
247 for release in tmp_releases:191 state = "needs-triage"
248 if release == cve_lib.devel_release or release == '':192 if not pkg_in_rel(p, rel):
249 release = 'devel'193 # package doesn't exist in this release - see if it wants a
250194 # DNE entry
251 # skip eol_releases releases without esm support195 if release_wants_dne(rel):
252 if release in cve_lib.eol_releases \196 state = "DNE"
253 and not cve_lib.is_active_esm_release(release):197 else:
198 continue
199 if rel == cve_lib.devel_release:
200 # devel is present in source.keys() so use that instead
201 # of the codename
254 continue202 continue
203 if cve_lib.is_active_esm_release(rel):
204 state = "ignored (out of standard support)"
205 elif rel == 'upstream' and fixed_in is not None:
206 state = "released (%s)" % fixed_in
207 elif fixed_in_release_version and rel == fixed_in_release:
208 state = "not-affected (%s)" % fixed_in_release_version
209 higher_not_affected = True
210 elif higher_not_affected:
211 state = "not-affected"
212
213 # use pkg_db state if one exists
214 if p in pkg_db and p in pkg_db[p]["pkgs"] and rel in pkg_db[p]["pkgs"][p]:
215 state_tuple = pkg_db[p]["pkgs"][p][rel]
216 state = state_tuple[0]
217 if len(state_tuple[1]) > 0:
218 state = state + " (%s)" % state_tuple[1]
219 if rel not in cve_lib.external_releases:
220 print('%s_%s: %s' % (rel, p, state), file=fp)
221 else:
222 # add this to subprojects for rel
223 with open(os.path.join(cve_lib.get_external_subproject_cve_dir(rel), cve), "a") as f:
224 print('%s_%s: %s' % (rel, p, state), file=f)
255225
256 rel_pat = re.compile('#?' + release + '_')
257
258 if (rel_pat.search(line)):
259 state = "needs-triage"
260 if not pkg_in_rel(pkgname, release):
261 # package doesn't exist in this release - see if it wants a
262 # DNE entry
263 if release_wants_dne(release):
264 state = "DNE"
265 else:
266 continue
267 elif cve_lib.is_active_esm_release(release):
268 state = "ignored (out of standard support)"
269 elif release == 'upstream' and fixed_in is not None:
270 state = "released (%s)" % fixed_in
271 elif fixed_in_release_version and release == fixed_in_release:
272 state = "not-affected (%s)" % fixed_in_release_version
273 higher_not_affected = True
274 elif higher_not_affected:
275 state = "not-affected"
276 if release not in added:
277 contents += "%s_%s: %s\n" % (release, pkgname, state)
278 added.add(release)
279 elif ref_pat.search(line):
280 if not re.search(r'N', cve):
281 contents += line + "\n https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + cve + "\n"
282 else:
283 contents += line + "\n"
284 if options.ref_urls:
285 for i in options.ref_urls:
286 contents += " %s\n" % i
287 elif options.bug_urls and bugs_pat.search(line):
288 contents += line
289 for i in options.bug_urls:
290 contents += "\n %s\n" % i
291 else:
292 contents += line + '\n'
293
294 # check for missing entries which aren't in the boilerplate
295 for release in tmp_releases:
296 if release == cve_lib.devel_release or release == '':
297 release = 'devel'
298 if release in added:
299 continue
300 if release in cve_lib.external_releases:
301 continue
302 # skip eol_releases releases without esm support
303 if release in cve_lib.eol_releases \
304 and not cve_lib.is_active_esm_release(release):
305 continue
306 if pkg_in_rel(pkgname, release):
307 state = "needs-triage"
308 contents += "%s_%s: %s\n" % (release, pkgname, state)
309
310 # for each line in contents, see if we need to supercede DNE status
311 # with needs-triage as boilerplate entries may not be up-to-date with
312 # xxx-supported.txt lists
313 pkgstatus_pat = re.compile(r'^([/a-z/\-]+)_(.*): (.*)')
314 old_contents = contents
315 contents = ""
316 for line in old_contents.splitlines():
317 match = pkgstatus_pat.search(line)
318 if match is not None:
319 release = match.group(1)
320 pkgname = match.group(2)
321 status = match.group(3)
322 if status == 'DNE' and pkg_in_rel(pkgname, release):
323 status = 'needs-triage'
324 line = '%s_%s: %s' % (release, pkgname, status)
325 contents += line + '\n'
326
327 if not options.autoconfirm:
328 print(contents)
329 print("\nWrite the above to " + os.path.join(cvedir, cve) + " (y|N)? ")
330 ans = sys.stdin.readline().lower()
331 print("\n")
332 else:
333 ans = "y"
334
335 if ans.startswith("y"):
336 newfile = open(os.path.join(cvedir, cve), 'w')
337 newfile.write(contents)
338 newfile.close()
339 else:
340 print("Aborted\n")
341226
342227
228pkg_db = cve_lib.load_package_db()
343229
344if not options.pkgs:230if not options.pkgs:
345 parser.print_help()231 parser.print_help()
@@ -369,37 +255,5 @@ if not pat.search(cve):
369 print("Bad CVE entry. Should be CVE-XXXX-XXXX\n", file=sys.stderr)255 print("Bad CVE entry. Should be CVE-XXXX-XXXX\n", file=sys.stderr)
370 sys.exit(1)256 sys.exit(1)
371257
372# more here258create_or_update_cve(cve, pkgs, priority=options.priority, bug_urls=options.bug_urls, ref_urls=options.ref_urls, public_date=options.public_date, cvss=options.cvss)
373pat = re.compile(r'\s')
374for p in pkgs:
375 tmp_p = p.split(',')
376 pkgname = tmp_p[0]
377 fixed_in = None
378 if len(tmp_p) > 1:
379 fixed_in = tmp_p[1]
380 fixed_in_release = None
381 fixed_in_release_version = None
382 if len(tmp_p) > 3:
383 fixed_in_release = tmp_p[2]
384 fixed_in_release_version = tmp_p[3]
385
386 if pat.search(pkgname):
387 print("Bad package name\n", file=sys.stderr)
388 sys.exit(1)
389
390 if not os.path.isfile(os.path.join(boilerplates, "00boilerplate")):
391 print("Could not find 00boilerplate in " + cvedir + "\n", file=sys.stderr)
392 sys.exit(1)
393
394 if (os.path.isfile(os.path.join(cvedir, cve))):
395 if not options.autoconfirm:
396 print("Found existing " + cve + "...\n\n")
397 update_cve(cve, pkgname, fixed_in, fixed_in_release, fixed_in_release_version)
398 else:
399 if not options.autoconfirm:
400 print("Creating new " + cve + "...\n\n")
401 create_cve(cve, pkgname, fixed_in, fixed_in_release, fixed_in_release_version)
402
403 create_or_update_external_subproject_cves(cve, pkgname)
404
405sys.exit(0)259sys.exit(0)
diff --git a/scripts/add-derived-kernel b/scripts/add-derived-kernel
index d219586..3c146ab 100755
--- a/scripts/add-derived-kernel
+++ b/scripts/add-derived-kernel
@@ -67,19 +67,37 @@ if [ -z "${DERIVED_KERNEL}" ] ; then
67 DERIVED_KERNEL="linux"67 DERIVED_KERNEL="linux"
68fi68fi
6969
70chunk=$(mktemp -t add-derived-kernel-XXXXXX)70releases=$(PYTHONPATH=./scripts python3 -c "import cve_lib; print(' '.join([a for a in cve_lib.all_releases if a not in cve_lib.external_releases and a is not cve_lib.devel_release and (a not in cve_lib.eol_releases or cve_lib.is_active_esm_release(a))]))")
71
72releases="upstream ${releases} devel"
7173
74chunk=$(mktemp -t add-derived-kernel-XXXXXX)
72echo "" > "$chunk"75echo "" > "$chunk"
73grep "^.*_linux:" active/00boilerplate.linux | sed -e "s#_linux:.*#_linux-${KERNEL}: DNE#" >> "$chunk"76echo "Patches_linux-${KERNEL}:" >> "$chunk"
74sed -i -e "s#^${RELEASE}_linux-${KERNEL}:.*#${RELEASE}_linux-${KERNEL}: needs-triage#" "$chunk"77
75sed -i -e "s#^Patches_linux-${KERNEL}:.*#Patches_linux-${KERNEL}:#" "$chunk"78json="{"
76sed -i -e "s#^upstream_linux-${KERNEL}:.*#upstream_linux-${KERNEL}: needs-triage#" "$chunk"79
7780# add other releases
78if ! grep -q "^${RELEASE}_linux-${KERNEL}:" active/00boilerplate.linux ; then81for rel in $releases; do
79 echo "Updating 00boilerplate.linux..."82 status="DNE"
80 cat "$chunk" >> active/00boilerplate.linux83 if [ "${rel}" = "${RELEASE}" ] || [ "${rel}" = "upstream" ] ; then
84 status="needs-triage"
85 fi
86 json="$json\"${rel}_${DERIVED_KERNEL}\": [\"$status\", \"\"],"
87 echo "${rel}_linux-${KERNEL}: ${status}" >> "$chunk"
88done
89# remove trailing comma
90json=${json%?}
91# close json objects
92json="$json}"
93
94# append the derived kernel to meta_lists/package-db.json if it doesn't exist already
95if jq -e ".linux.pkgs.\"linux-$KERNEL\"" meta_lists/package-db.json; then
96 echo "kernel linux-${KERNEL} already exists in meta_lists/package-db.json, skipping update."
81else97else
82 echo "00boilerplate.linux already contains linux-${KERNEL}, skipping update."98 echo "adding kernel linux-${KERNEL} to meta_lists/package-db.json"
99 jq -e ".linux.pkgs.\"linux-$KERNEL\" += $json" meta_lists/package-db.json > meta_lists/package-db.json.new
100 mv meta_lists/package-db.json.new meta_lists/package-db.json
83fi101fi
84102
85echo "Adding new backport to existing CVEs..."103echo "Adding new backport to existing CVEs..."
@@ -105,6 +123,10 @@ echo "Updating status of released CVEs (ok if empty and prints help)..."
105 xargs --no-run-if-empty ./scripts/mass-cve-edit -p "linux-${KERNEL}" -r "${RELEASE}" -s not-affected123 xargs --no-run-if-empty ./scripts/mass-cve-edit -p "linux-${KERNEL}" -r "${RELEASE}" -s not-affected
106124
107printf "\n\nPlease update cve_lib.py, kernel_lib.py, sis-generate-usn, cve-alert.sh, and prepare-kernel-usn.py in scripts/\n"125printf "\n\nPlease update cve_lib.py, kernel_lib.py, sis-generate-usn, cve-alert.sh, and prepare-kernel-usn.py in scripts/\n"
108echo "Please add package description information if necessary to meta_lists/package_info_overrides.json"126echo "Please add package description information if necessary to meta_lists/package-db.json"
109echo "If this kernel has not been published yet, please add it to the unpublished_kernels list in check-syntax."127echo "If this kernel has not been published yet, please add it to the unpublished_kernels list in check-syntax."
110echo "Also, before publishing a USN against the new kernel, ensure packages_mirror has been run"128echo "Also, before publishing a USN against the new kernel, ensure packages_mirror has been run"
129
130# Local Variables:
131# sh-indentation: 4
132# End:
diff --git a/scripts/add_meta_info.py b/scripts/add_meta_info.py
index 994c8ec..d5b78c3 100755
--- a/scripts/add_meta_info.py
+++ b/scripts/add_meta_info.py
@@ -10,11 +10,13 @@ if len(sys.argv) != 4:
10package = sys.argv[1]10package = sys.argv[1]
11title = sys.argv[2]11title = sys.argv[2]
12description = sys.argv[3]12description = sys.argv[3]
13json_file = os.environ['UCT'] + "/meta_lists/package_info_overrides.json"13json_file = os.environ['UCT'] + "/meta_lists/package-db.json"
1414
15with open(json_file, 'r') as handle:15with open(json_file, 'r') as handle:
16 parsed = json.load(handle)16 parsed = json.load(handle)
17 parsed[package] = { "description": description, 'title': title }17 parsed.setdefault(package, {})
18 parsed[package]['title'] = title
19 parsed[package]['description'] = description
18 new_content = json.dumps(parsed, indent=4, sort_keys=True)20 new_content = json.dumps(parsed, indent=4, sort_keys=True)
1921
20with open(json_file, 'w') as handle:22with open(json_file, 'w') as handle:
diff --git a/scripts/boilerplate-to-json.py b/scripts/boilerplate-to-json.py
21new file mode 10075523new file mode 100755
index 0000000..db2c735
--- /dev/null
+++ b/scripts/boilerplate-to-json.py
@@ -0,0 +1,151 @@
1#!/usr/bin/python3
2import glob
3import json
4import os
5import re
6import sys
7
8import cve_lib
9
10def parse_boilerplate(filepath):
11 cve_data = cve_lib.load_cve(filepath)
12 # capture tags, Notes, and package relationships
13 data = dict()
14 data.setdefault("aliases", list())
15 # tags are a set but json can't serialise a set so convert to a list first
16 data.setdefault("tags", list(cve_data.get("tags", list())))
17 data.setdefault("notes", cve_data.get("Notes", list()))
18 data.setdefault("pkgs", cve_data.get("pkgs", dict()))
19 return data
20
21
22def load_boilerplates():
23 data = dict()
24 aliases = dict()
25 for filepath in glob.glob("active/00boilerplate.*"):
26 name = ".".join(filepath.split(".")[1:])
27 # check if is a symlink and if so don't bother loading the file
28 # directly but add an entry as this is an alias
29 if os.path.islink(filepath):
30 orig = os.readlink(filepath)
31 orig_name = ".".join(orig.split(".")[1:])
32 aliases.setdefault(orig_name, set())
33 aliases[orig_name].add(name)
34 continue
35 bpdata = parse_boilerplate(filepath)
36 # having a package reference itself as we have in the boilerplates
37 # is redundant - although this is not always the case as we may
38 # have a boilerplate filename like openjdk yet there is no openjdk
39 # package (just openjdk-8 etc) - so ignore any failures here
40 try:
41 del bpdata["pkgs"][name]
42 except KeyError:
43 pass
44 data.setdefault(name, bpdata)
45 for alias in aliases:
46 data[alias]["aliases"] = list(aliases[alias])
47 return data
48
49
50def load_package_info_overrides():
51 with open("meta_lists/package_info_overrides.json", "r") as fp:
52 data = json.load(fp)
53 return data
54
55
56overrides_data = load_package_info_overrides()
57# turn this into empty data
58for pkg in overrides_data:
59 for key in ["aliases", "tags", "notes"]:
60 overrides_data[pkg][key] = []
61 overrides_data[pkg]["pkgs"] = {}
62bp_data = load_boilerplates()
63# merge the two data sources
64data = {**overrides_data, **bp_data}
65
66print(json.dumps(data, indent=2))
67sys.exit(0)
68
69# TODO - decide if we want to keep this - for now leave it out
70
71def parse_embedded_code_copies(filepath):
72 begin_re = re.compile(r"^---BEGIN$")
73 pkg_re = re.compile(r"^([a-zA-Z0-9.+_-]+).*$")
74 # [release] - srcpkg version|<status> (sort; bug #)
75 embedding_re = re.compile(r"^\t(\[([a-z]+)\] )?- ([a-zA-Z0-9.+-]+) ([a-zA-Z0-9:~.+-]+|<(unfixed|removed|itp|not-affected|unknown|unfixable)>)( \((static|embed|modified-embed|fork|old-version)(; (.*))?\))?.*$")
76 note_re = re.compile(r"^\tNOTE: (.*)$")
77 data = dict()
78 pkgs = dict()
79 notes = dict()
80 with open(filepath, "r") as fp:
81 linenum = 0
82 begin = False
83 pkg = None
84 embedding_pkg = None
85 for line in fp.readlines():
86 linenum += 1
87 # strip trailing space
88 line = line.rstrip()
89 if not begin:
90 if begin_re.match(line):
91 begin = True
92 continue
93 if len(line) == 0:
94 continue
95 # is this a new package
96 m = pkg_re.match(line)
97 if m is not None:
98 pkg = m[1]
99 pkgs[pkg] = dict()
100 continue
101 # is this an entry for a package
102 m = embedding_re.match(line)
103 if m is not None:
104 assert pkg is not None
105 if m[2] is not None:
106 # release
107 pass
108 embedding_pkg = m[3]
109 status = m[4]
110 sort = m[7]
111 pkgs[pkg][embedding_pkg] = (status, sort)
112 continue
113 m = note_re.match(line)
114 if m is not None:
115 assert pkg is not None
116 assert embedding_pkg is not None
117 notes.setdefault(pkg, dict())
118 notes[pkg][embedding_pkg] = m[1]
119 continue
120 print("%s: %d: Failed to parse: '%s'" % (filepath, linenum, line), file=sys.stderr)
121 data["pkgs"] = pkgs
122 data["notes"] = notes
123 return data
124
125# also parse debian's embedded-code-copies and amalgate that into data
126config = cve_lib.read_config()
127debian_embedded_copies = os.path.join(config['secure_testing_path'], "data", "embedded-code-copies")
128code_copies = parse_embedded_code_copies(debian_embedded_copies)
129for pkg in code_copies["pkgs"]:
130 data.setdefault(pkg, {"aliases": [],
131 "tags": [],
132 "notes": [],
133 "pkgs": {}})
134 for embedding_pkg in code_copies["pkgs"][pkg]:
135 data[pkg]["pkgs"].setdefault(embedding_pkg, ("needs-triage", ""))
136 # use the sort to create a more informative description of the
137 # relationship between pkg and embedding_pkg
138 status, sort = code_copies["pkgs"][pkg][embedding_pkg]
139 template = "%s embeds a copy of %s"
140 if sort == "static":
141 template = "%s statically links against %s so needs to be rebuilt"
142 elif sort == "modified-embed":
143 template = "%s embeds a modified copy of %s so should be checked if is affected"
144 elif sort == "fork":
145 template = "%s contains a fork of %s so should be checked if is affected"
146 elif sort == "old-version":
147 template = "%s contains an older version of %s so should be checked if is affected"
148 note = template % (embedding_pkg, pkg)
149 if pkg in code_copies["notes"] and embedding_pkg in code_copies["notes"][pkg]:
150 note = note + " - " + code_copies["notes"][pkg][embedding_pkg]
151 data[pkg]["notes"].append(("dst", note))
diff --git a/scripts/check-cves b/scripts/check-cves
index fa6093d..963f7d3 100755
--- a/scripts/check-cves
+++ b/scripts/check-cves
@@ -34,7 +34,6 @@ import xml.sax
34import xml.sax.handler34import xml.sax.handler
35import xml.sax.xmlreader35import xml.sax.xmlreader
36from html import escape36from html import escape
37from functools import reduce
38import progressbar37import progressbar
3938
40import cve_lib39import cve_lib
@@ -75,9 +74,10 @@ for release in list(source.keys()):
75# likely to sometimes contain these74# likely to sometimes contain these
76common_words = ['an', 'and', 'context', 'file', 'modules', 'the', 'when']75common_words = ['an', 'and', 'context', 'file', 'modules', 'the', 'when']
77allsrcs.difference_update(set(common_words))76allsrcs.difference_update(set(common_words))
78# add boilerplate names too so we can get mysql or postgresql77# add names and aliases etc from package-db
79# etc even if they don't exist as source package names78allsrcs.update(set(cve_lib.package_db.keys()))
80allsrcs.update(set(cve_lib.load_boilerplates().keys()))79for pkg in cve_lib.package_db:
80 allsrcs.update(set(cve_lib.package_db[pkg]["aliases"]))
8181
82built_using_map = None82built_using_map = None
8383
@@ -124,24 +124,8 @@ def subtract_list(list1, list2):
124 list1.remove(item)124 list1.remove(item)
125125
126126
127def wordwrap(text, width):
128 """
129 A word-wrap function that preserves existing line breaks
130 and most spaces in the text. Expects that existing line
131 breaks are posix newlines (\n).
132 """
133 return reduce(lambda line, word, width=width: '%s%s%s' %
134 (line,
135 ' \n'[(len(line) - line.rfind('\n') - 1 +
136 len(word.split('\n', 1)[0]
137 ) >= width)],
138 word),
139 text.split(' ')
140 )
141
142
143def _wrap_desc(desc):127def _wrap_desc(desc):
144 return wordwrap(desc, 75).replace(' \n', '\n')128 return cve_lib.wrap_text(desc)
145129
146def _spawn_editor(path):130def _spawn_editor(path):
147 editor = os.getenv('EDITOR', 'vi')131 editor = os.getenv('EDITOR', 'vi')
@@ -164,104 +148,6 @@ def prompt_user(msg):
164 print(msg, flush=True, end='')148 print(msg, flush=True, end='')
165149
166150
167def add_CVE_to_tracker(cve, info, packages, priority=None, bug_urls=[], ref_urls=[]):
168 src = '%s/active/00boilerplate' % (destdir)
169
170 # Use the first boilerplate for template
171 first_boiler = ""
172 for b in packages:
173 if os.path.exists(src + "." + b):
174 src = src + "." + b
175 first_boiler = src
176 break
177 dst = '%s/active/%s' % (destdir, cve)
178 with open(src) as f:
179 template = f.readlines()
180 cve_file = open(dst, 'w')
181 orig_priority = ""
182 for line in template:
183 line = line.rstrip()
184 if line.startswith('Candidate:'):
185 print('Candidate: %s' % (cve), file=cve_file)
186 elif info['public'] and line.startswith('PublicDate:'):
187 print('PublicDate: %s' % (info['public']), file=cve_file)
188 elif info['cvss'] and line.startswith('CVSS:'):
189 print('CVSS:', file=cve_file)
190 for entry in info['cvss']:
191 print(' %s: %s [%s %s]' % (entry['source'], entry['vector'], entry['baseScore'], entry['baseSeverity']), file=cve_file)
192 elif line.startswith('References:'):
193 print('References:\n https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s' % (cve), file=cve_file)
194 for i in ref_urls:
195 print(" %s" % i, file=cve_file)
196 elif line.startswith('Bugs:'):
197 print(line, file=cve_file)
198 for i in bug_urls:
199 print(" %s" % i, file=cve_file)
200 elif line.startswith('Priority:'):
201 orig_priority = line.split()[1]
202 if priority:
203 print('Priority: %s' % priority, file=cve_file)
204 else:
205 print(line, file=cve_file)
206 elif not line.startswith('#'):
207 print(line, file=cve_file)
208
209 if line.startswith('Description:'):
210 for desc_line in _wrap_desc(info['desc']).split('\n'):
211 print(" %s" % (desc_line), file=cve_file)
212
213 # Now add package information (with Priority_<pkg>) from other boilers
214 if len(packages) > 1:
215 for p in packages:
216 skip_emptyline = False
217 boiler = '%s/active/00boilerplate.%s' % (destdir, p)
218 if os.path.exists(boiler) and boiler != first_boiler:
219 with open(boiler) as f:
220 template = f.readlines()
221 in_note_section = False
222 for line in template:
223 line = line.rstrip()
224 # handle notes in templates
225 if in_note_section:
226 if line.startswith(' '):
227 continue
228 else:
229 in_note_section = False
230 if line.startswith('Notes:'):
231 in_note_section = True
232 continue
233 if line.startswith('Candidate:') or \
234 line.startswith('PublicDate:') or \
235 line.startswith('References:') or \
236 line.startswith('Description:') or \
237 line.startswith('Ubuntu-Description:') or \
238 line.startswith('Bugs:') or \
239 line.startswith('Discovered-by:') or \
240 line.startswith('Assigned-to:') or \
241 line.startswith('#'):
242 continue
243 if line.startswith('Priority:'):
244 new_priority = line.split()[1]
245 if priority:
246 continue
247 elif new_priority == orig_priority:
248 continue
249 elif orig_priority == "":
250 print(line, file=cve_file)
251 else:
252 print('Priority_%s: %s' % (p, new_priority), file=cve_file)
253 skip_emptyline = True
254 elif skip_emptyline and line == "":
255 skip_emptyline = False
256 continue
257 else:
258 print(line, file=cve_file)
259 print("")
260
261 cve_file.close()
262
263 return dst
264
265151
266class PercentageFile(object):152class PercentageFile(object):
267 def __init__(self, filename):153 def __init__(self, filename):
@@ -1371,110 +1257,114 @@ class CVEHandler(xml.sax.handler.ContentHandler):
1371 print('%s %s %s\n%s' % (action, cve, data, desc))1257 print('%s %s %s\n%s' % (action, cve, data, desc))
13721258
1373 def add_cve(self, cve, packages, priority=None):1259 def add_cve(self, cve, packages, priority=None):
1374 # remove from not-for-us.txt if adding and ensure we remove any1260 # remove from not-for-us.txt if adding and ensure we remove any
1375 # mistriaged_hint from the description1261 # mistriaged_hint from the description
1376 if cve in CVEIgnoreNotForUsList:1262 if cve in CVEIgnoreNotForUsList:
1377 cmd = ['sed', '-i', '/^%s #.*$/d' % cve, './ignored/not-for-us.txt']1263 cmd = ['sed', '-i', '/^%s #.*$/d' % cve, './ignored/not-for-us.txt']
1378 subprocess.call(cmd)1264 subprocess.call(cmd)
1379 self.cve_data[cve]['desc'] = self.cve_data[cve]['desc'].replace(mistriaged_hint, '')1265 self.cve_data[cve]['desc'] = self.cve_data[cve]['desc'].replace(mistriaged_hint, '')
13801266
1381 # Build up list of reference urls1267 # Build up list of reference urls
1382 ref_urls = []1268 ref_urls = []
1269 if self.debian and \
1270 cve in self.debian and \
1271 'note' in self.debian[cve]:
1272 for line in self.debian[cve]['note']:
1273 tmp = line.lstrip("NOTE: ")
1274 if tmp.startswith("http"):
1275 ref_urls.append(tmp)
1276 if 'refs' in self.cve_data[cve]:
1277 for ref in self.cve_data[cve]['refs']:
1278 url = ""
1279 if ref[1].strip().startswith("http"):
1280 url = ref[1].strip()
1281 elif ref[2] is not None and ref[2].strip().startswith("http"):
1282 url = ref[2].strip()
1283 else: # no urls
1284 continue
1285
1286 if '//' not in url: # invalid url
1287 continue
1288
1289 # ignore certain reference URLs which we don't use
1290 ignored_urls = ['www.securityfocus.com', 'www.osvdb.org']
1291 if url.split('//')[1].split('/')[0] in ignored_urls:
1292 continue
1293
1294 if url not in ref_urls:
1295 ref_urls.append(url)
1296
1297 # Build up list of bug urls
1298 bug_urls = []
1299 for pkg in packages:
1383 if self.debian and \1300 if self.debian and \
1384 cve in self.debian and \1301 cve in self.debian and \
1385 'note' in self.debian[cve]:1302 self.debian[cve]['pkgs'] and \
1386 for line in self.debian[cve]['note']:1303 pkg in self.debian[cve]['pkgs']:
1387 tmp = line.lstrip("NOTE: ")1304 bug = None
1388 if tmp.startswith("http"):1305 if self.debian[cve]['pkgs'][pkg]['priority'] and \
1389 ref_urls.append(tmp)1306 re.search(r'^bug #[0-9]+$', self.debian[cve]['pkgs'][pkg]['priority']):
1390 if 'refs' in self.cve_data[cve]:1307 bug = self.debian[cve]['pkgs'][pkg]['priority'].split('#')[1]
1391 for ref in self.cve_data[cve]['refs']:1308 elif self.debian[cve]['pkgs'][pkg]['bug']:
1392 url = ""1309 bug = self.debian[cve]['pkgs'][pkg]['bug']
1393 if ref[1].strip().startswith("http"):1310 if bug:
1394 url = ref[1].strip()1311 url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s" % bug
1395 elif ref[2] is not None and ref[2].strip().startswith("http"):1312 if url not in bug_urls:
1396 url = ref[2].strip()1313 bug_urls.append(url)
1397 else: # no urls1314
1398 continue1315
13991316 # Build up command line
1400 if '//' not in url: # invalid url1317 cmd = ['./scripts/active_edit', '-c', cve, '--yes']
1401 continue1318 for url in ref_urls:
14021319 cmd.extend(['--reference-url', url])
1403 # ignore certain reference URLs which we don't use1320 for url in bug_urls:
1404 ignored_urls = ['www.securityfocus.com', 'www.osvdb.org']1321 cmd.extend(['--bug-url', url])
1405 if url.split('//')[1].split('/')[0] in ignored_urls:1322 if priority:
1406 continue1323 cmd.extend(['--priority', priority])
14071324
1408 if url not in ref_urls:1325 # capture debian not-affected states
1409 ref_urls.append(url)1326 not_affected = []
14101327
1411 # Build up list of bug urls1328 for pkg in packages:
1412 bug_urls = []1329 # The Debian convention is to specify the fixed version as the state
1413 for pkg in packages:1330 # with the bug number as the priority for fixed bugs. Leverage this
1414 if self.debian and \1331 # with active_edit
1415 cve in self.debian and \1332 fixed_in = ""
1416 self.debian[cve]['pkgs'] and \1333 if self.debian and \
1417 pkg in self.debian[cve]['pkgs']:1334 cve in self.debian and \
1418 bug = None1335 self.debian[cve]['pkgs'] and \
1419 if self.debian[cve]['pkgs'][pkg]['priority'] and \1336 pkg in self.debian[cve]['pkgs'] and \
1420 re.search(r'^bug #[0-9]+$', self.debian[cve]['pkgs'][pkg]['priority']):1337 self.debian[cve]['pkgs'][pkg]['state']:
1421 bug = self.debian[cve]['pkgs'][pkg]['priority'].split('#')[1]1338 if re.search(r'^[0-9]', self.debian[cve]['pkgs'][pkg]['state']):
1422 elif self.debian[cve]['pkgs'][pkg]['bug']:1339 fixed_version = self.debian[cve]['pkgs'][pkg]['state']
1423 bug = self.debian[cve]['pkgs'][pkg]['bug']1340 fixed_in = ",%s" % fixed_version
1424 if bug:1341
1425 url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s" % bug1342 # Now see if we can correlate this to an Ubuntu version
1426 if url not in bug_urls:1343 answer = source_map.madison(source, pkg)
1427 bug_urls.append(url)1344 for name in sorted(answer.keys()):
14281345 rel = name.split('/')[0].split('-')[0] # don't care about the pocket
1429 # Add to tracker from 00boilerplate1346 version = answer[name][pkg]
1430 dst = add_CVE_to_tracker(cve, self.cve_data[cve], packages, priority, bug_urls, ref_urls)1347 # Try to compare apples to apples. Ie, if one of us has
14311348 # an epoch and the other doesn't, don't try to be smart
1432 # Build up command line1349 if (':' not in version and ':' not in fixed_version) or \
1433 cmd = ['./scripts/active_edit', '-c', cve, '--yes']1350 (':' in version and ':' in fixed_version):
14341351 if dpkg_compare_versions(version, 'ge', fixed_version):
1435 # capture debian not-affected states1352 if rel == cve_lib.devel_release:
1436 not_affected = []1353 rel = 'devel'
14371354 fixed_in += ",%s,%s" % (rel, version)
1438 for pkg in packages:1355 break
1439 # The Debian convention is to specify the fixed version as the state1356 elif self.debian[cve]['pkgs'][pkg]['state'].startswith('<not-affected>') and \
1440 # with the bug number as the priority for fixed bugs. Leverage this1357 len(self.debian[cve]['pkgs'][pkg]['priority']) > 0:
1441 # with active_edit1358 # capture that debian believes their version is unaffected
1442 fixed_in = ""1359 not_affected.append((pkg, "debian: %s" % self.debian[cve]['pkgs'][pkg]['priority']))
1443 if self.debian and \1360 cmd += ['-p', "%s%s" % (pkg, fixed_in)]
1444 cve in self.debian and \1361
1445 self.debian[cve]['pkgs'] and \1362 subprocess.call(cmd)
1446 pkg in self.debian[cve]['pkgs'] and \1363 for (pkg, reason) in not_affected:
1447 self.debian[cve]['pkgs'][pkg]['state']:1364 cmd = ['./scripts/mass-cve-edit', '-p', pkg, '-r', 'upstream', '-s', 'not-affected', '-v', reason, cve]
1448 if re.search(r'^[0-9]', self.debian[cve]['pkgs'][pkg]['state']):
1449 fixed_version = self.debian[cve]['pkgs'][pkg]['state']
1450 fixed_in = ",%s" % fixed_version
1451
1452 # Now see if we can correlate this to an Ubuntu version
1453 answer = source_map.madison(source, pkg)
1454 for name in sorted(answer.keys()):
1455 rel = name.split('/')[0].split('-')[0] # don't care about the pocket
1456 version = answer[name][pkg]
1457 # Try to compare apples to apples. Ie, if one of us has
1458 # an epoch and the other doesn't, don't try to be smart
1459 if (':' not in version and ':' not in fixed_version) or \
1460 (':' in version and ':' in fixed_version):
1461 if dpkg_compare_versions(version, 'ge', fixed_version):
1462 if rel == cve_lib.devel_release:
1463 rel = 'devel'
1464 fixed_in += ",%s,%s" % (rel, version)
1465 break
1466 elif self.debian[cve]['pkgs'][pkg]['state'].startswith('<not-affected>') and \
1467 len(self.debian[cve]['pkgs'][pkg]['priority']) > 0:
1468 # capture that debian believes their version is unaffected
1469 not_affected.append((pkg, "debian: %s" % self.debian[cve]['pkgs'][pkg]['priority']))
1470 cmd += ['-p', "%s%s" % (pkg, fixed_in)]
1471
1472 subprocess.call(cmd)1365 subprocess.call(cmd)
1473 for (pkg, reason) in not_affected:1366 self.num_added += 1
1474 cmd = ['./scripts/mass-cve-edit', '-p', pkg, '-r', 'upstream', '-s', 'not-affected', '-v', reason, cve]1367 return './active/%s' % cve
1475 subprocess.call(cmd)
1476 self.num_added += 1
1477 return dst
14781368
1479 def unembargo_cve(self, cve):1369 def unembargo_cve(self, cve):
1480 # unembargo a cve now public1370 # unembargo a cve now public
diff --git a/scripts/check-syntax b/scripts/check-syntax
index 9501d58..234c71a 100755
--- a/scripts/check-syntax
+++ b/scripts/check-syntax
@@ -279,7 +279,7 @@ if len(args) == 0:
279 with open(opt.filelist) as fh:279 with open(opt.filelist) as fh:
280 for line in fh:280 for line in fh:
281 for dir in check_dirs:281 for dir in check_dirs:
282 if line.startswith("%s/CVE-" % dir) or line.startswith("%s/00boilerplate" % dir):282 if line.startswith("%s/CVE-" % dir):
283 args += [line.rstrip()]283 args += [line.rstrip()]
284 elif opt.modified:284 elif opt.modified:
285 if opt.debug:285 if opt.debug:
@@ -299,11 +299,7 @@ if len(args) == 0:
299 args += [filename]299 args += [filename]
300 else:300 else:
301 for dir in check_dirs:301 for dir in check_dirs:
302 # XXX might want to separate out boilerplate checks302 for cve in sorted(glob.glob("%s/CVE-*" % dir)):
303 # as they might need to be less restrictive than regular CVE
304 # file checks
305 for cve in sorted(glob.glob("%s/CVE-*" % dir) +
306 glob.glob("%s/00boilerplate.*" % dir)):
307 args += [cve]303 args += [cve]
308else:304else:
309 all_files = False305 all_files = False
@@ -404,7 +400,7 @@ for cve in args:
404 cve_okay = False400 cve_okay = False
405401
406 # verify candidate field matches the CVE file name402 # verify candidate field matches the CVE file name
407 if "stdin" not in cve and "boilerplate" not in cve and not data["Candidate"] == cve:403 if "stdin" not in cve and not data["Candidate"] == cve:
408 filename = srcmap["Candidate"][0]404 filename = srcmap["Candidate"][0]
409 linenum = srcmap["Candidate"][1]405 linenum = srcmap["Candidate"][1]
410 print(406 print(
@@ -424,10 +420,9 @@ for cve in args:
424 # place the generated error message on this release's line etc420 # place the generated error message on this release's line etc
425 nearby_rel = list(listed_releases - missing_releases)[0]421 nearby_rel = list(listed_releases - missing_releases)[0]
426 for rel in missing_releases:422 for rel in missing_releases:
427 # only warn on active CVEs but don't warn on boilerplate entries missing external423 # only warn on active CVEs
428 # releases as this is not supported
429 if is_active(cve) and \424 if is_active(cve) and \
430 ("boilerplate" not in cve or rel not in cve_lib.external_releases) and \425 rel not in cve_lib.external_releases and \
431 rel in source and pkg in source[rel]:426 rel in source and pkg in source[rel]:
432 filename = srcmap["pkgs"][pkg][nearby_rel][0]427 filename = srcmap["pkgs"][pkg][nearby_rel][0]
433 linenum = srcmap["pkgs"][pkg][nearby_rel][1]428 linenum = srcmap["pkgs"][pkg][nearby_rel][1]
@@ -658,10 +653,8 @@ for cve in args:
658 )653 )
659 cve_okay = False654 cve_okay = False
660655
661 # Verify priority for any CVE with a supported package and when this is656 # Verify priority for any CVE with a supported package
662 # not boilerplate
663 if (657 if (
664 "boilerplate" not in cve and
665 len(supported)658 len(supported)
666 and (is_active(cve) or is_embargoed(cve))659 and (is_active(cve) or is_embargoed(cve))
667 and ("Priority" not in data or data["Priority"] not in cve_lib.priorities)660 and ("Priority" not in data or data["Priority"] not in cve_lib.priorities)
@@ -777,10 +770,10 @@ for cve in args:
777 cve_okay = False770 cve_okay = False
778771
779 # Either PublicDate or CRD must be set to something772 # Either PublicDate or CRD must be set to something
780 if ("boilerplate" not in cve and773 if (
781 ("PublicDate" not in data or data["PublicDate"] == "") and (774 "PublicDate" not in data or data["PublicDate"] == "" and
782 "CRD" not in data or data["CRD"] == ""775 "CRD" not in data or data["CRD"] == ""
783 )):776 ):
784 key = "PublicDate" if "PublicDate" in srcmap else "CRD"777 key = "PublicDate" if "PublicDate" in srcmap else "CRD"
785 filename = srcmap[key][0]778 filename = srcmap[key][0]
786 linenum = srcmap[key][1]779 linenum = srcmap[key][1]
diff --git a/scripts/check-syntax-fixup b/scripts/check-syntax-fixup
index 24bf608..a38ad1e 100755
--- a/scripts/check-syntax-fixup
+++ b/scripts/check-syntax-fixup
@@ -147,11 +147,6 @@ for line in args.infile:
147 # remove this hard-coded hack one-day...147 # remove this hard-coded hack one-day...
148 if rel in cve_lib.external_releases or \148 if rel in cve_lib.external_releases or \
149 (rel == "trusty/esm" and "DOES exist" in msg):149 (rel == "trusty/esm" and "DOES exist" in msg):
150 # ignore boilerplate files for external_releases
151 if "boilerplate" in cve:
152 # print unhandled lines
153 print(line, file=sys.stderr)
154 continue
155 cve = os.path.join(150 cve = os.path.join(
156 cve_lib.get_external_subproject_cve_dir(rel), os.path.basename(cve)151 cve_lib.get_external_subproject_cve_dir(rel), os.path.basename(cve)
157 )152 )
diff --git a/scripts/cve-mode.el b/scripts/cve-mode.el
index b7413b0..0992e4c 100644
--- a/scripts/cve-mode.el
+++ b/scripts/cve-mode.el
@@ -333,7 +333,7 @@ Queries umt for PACKAGE as well as looking in overlay files."
333(defun cve-mode-insert-package (package)333(defun cve-mode-insert-package (package)
334 "Add PACKAGE as affected to this CVE.334 "Add PACKAGE as affected to this CVE.
335Calls out to active_edit to do the heavy lifting so that335Calls out to active_edit to do the heavy lifting so that
336boilerplate entries are handled automatically."336meta_lists/package-db.json entries are handled automatically."
337 (interactive337 (interactive
338 (list (completing-read "Package: " cve-mode--source-packages)))338 (list (completing-read "Package: " cve-mode--source-packages)))
339 (let ((args (list "-c" (file-name-base (buffer-file-name))339 (let ((args (list "-c" (file-name-base (buffer-file-name))
@@ -683,8 +683,6 @@ cross boundaries of block literals."
683683
684;;;###autoload684;;;###autoload
685(add-to-list 'auto-mode-alist '("CVE-[[:digit:]]\\{4\\}-[[:digit:]]\\{4,\\}\\'" . cve-mode))685(add-to-list 'auto-mode-alist '("CVE-[[:digit:]]\\{4\\}-[[:digit:]]\\{4,\\}\\'" . cve-mode))
686;;;###autoload
687(add-to-list 'auto-mode-alist '("00boilerplate.*\\'" . cve-mode))
688686
689(provide 'cve-mode)687(provide 'cve-mode)
690;;; cve-mode.el ends here688;;; cve-mode.el ends here
diff --git a/scripts/cve.vim b/scripts/cve.vim
index bc89578..a13b158 100644
--- a/scripts/cve.vim
+++ b/scripts/cve.vim
@@ -7,7 +7,6 @@
7" $ ln -s $UCT/scripts/cve.vim ~/.vim/syntax/cve.vim7" $ ln -s $UCT/scripts/cve.vim ~/.vim/syntax/cve.vim
8" Add to ~/.vimrc:8" Add to ~/.vimrc:
9" autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9N]\\\{4,\} set syntax=cve9" autocmd BufNewFile,BufRead CVE-[0-9][0-9][0-9][0-9]-[0-9N]\\\{4,\} set syntax=cve
10" autocmd BufNewFile,BufRead 00boilerplate.* set syntax=cve
11"10"
12" TODO:11" TODO:
13" - turn the release names into variables so we only have to update in one12" - turn the release names into variables so we only have to update in one
diff --git a/scripts/cve_lib.py b/scripts/cve_lib.py
index fe8e4f5..60da772 100755
--- a/scripts/cve_lib.py
+++ b/scripts/cve_lib.py
@@ -23,6 +23,8 @@ import cache_urllib
23import json23import json
24import yaml24import yaml
2525
26from functools import reduce
27
26def set_cve_dir(path):28def set_cve_dir(path):
27 '''Return a path with CVEs in it. Specifically:29 '''Return a path with CVEs in it. Specifically:
28 - if 'path' has CVEs in it, return path30 - if 'path' has CVEs in it, return path
@@ -912,11 +914,33 @@ kernel_srcs = set(['linux',
912kernel_topic_branches = kernel_srcs.difference(['linux'])914kernel_topic_branches = kernel_srcs.difference(['linux'])
913915
914# for sanity, try to keep these in alphabetical order in the json file916# for sanity, try to keep these in alphabetical order in the json file
915def load_package_info_overrides(list_dir):917def load_package_db(dir=meta_dir):
916 package_info_overrides = dict()918 pkg_db = {}
917 with open(os.path.join(list_dir, "package_info_overrides.json")) as _file:919 pkg_db_json = os.path.join(dir, "package-db.json")
918 package_info_overrides = json.load(_file)920 try:
919 return package_info_overrides921 with open(pkg_db_json, "r", encoding='utf-8') as fp:
922 pkg_db = json.load(fp)
923 # add lookups based on aliases - we can't iterate over pkg_db and
924 # modify it so collect aliases then add them manually
925 alias_info = {}
926 for p in pkg_db:
927 try:
928 aliases = pkg_db[p]["aliases"]
929 if len(aliases) > 0:
930 alias_info[p] = aliases
931 except KeyError:
932 pass
933 for p in alias_info.keys():
934 for a in alias_info[p]:
935 if a not in pkg_db:
936 # use original info if already in pkg_db
937 pkg_db[a] = pkg_db[p]
938 except FileNotFoundError:
939 # TODO: remove this exception handling once we have a package-db.json
940 # checked into UCT git since in that case this should never occur so it
941 # should be a fatal error if it is missing
942 pass
943 return pkg_db
920944
921945
922# "arch_list" is all the physical architectures buildable946# "arch_list" is all the physical architectures buildable
@@ -1226,19 +1250,19 @@ def release_is_older_than(release_a, release_b):
12261250
12271251
12281252
1229package_info_overrides = load_package_info_overrides(meta_dir)1253package_db = load_package_db()
12301254
1231def lookup_package_override_title(source):1255def lookup_package_override_title(source):
1232 global package_info_overrides1256 global package_db
1233 res = package_info_overrides.get(source)1257 res = package_db.get(source)
1234 if isinstance(res, dict):1258 if isinstance(res, dict):
1235 return(res.get("title"))1259 return(res.get("title"))
12361260
1237 return None1261 return None
12381262
1239def lookup_package_override_description(source):1263def lookup_package_override_description(source):
1240 global package_info_overrides1264 global package_db
1241 res = package_info_overrides.get(source)1265 res = package_db.get(source)
1242 if isinstance(res, dict):1266 if isinstance(res, dict):
1243 return(res.get("description"))1267 return(res.get("description"))
12441268
@@ -1964,9 +1988,6 @@ def load_cve(cve, strict=False, srcmap=None):
1964 nonempty = ['Candidate']1988 nonempty = ['Candidate']
1965 if strict:1989 if strict:
1966 nonempty += ['PublicDate']1990 nonempty += ['PublicDate']
1967 # boilerplate files are special and can (should?) be empty
1968 if "boilerplate" in cve:
1969 nonempty = []
19701991
1971 if field not in data or field not in fields_seen:1992 if field not in data or field not in fields_seen:
1972 msg += "%s: %d: missing field '%s'\n" % (cve, linenum, field)1993 msg += "%s: %d: missing field '%s'\n" % (cve, linenum, field)
@@ -2008,17 +2029,6 @@ def load_cve(cve, strict=False, srcmap=None):
2008 raise ValueError(msg.strip())2029 raise ValueError(msg.strip())
2009 return data2030 return data
20102031
2011def load_boilerplates(verbose=False):
2012 boilerplates = dict()
2013 prefix = "00boilerplate."
2014 for bp in glob.glob(os.path.join(active_dir, prefix + "*")):
2015 # TODO - should we differentiate on symlinks so we can tell which
2016 # are the "real" primary ones and which ones are secondary?
2017 name = bp[bp.find(prefix) + len(prefix):]
2018 info = load_cve(bp)
2019 boilerplates.setdefault(name, info)
2020 return boilerplates
2021
2022def load_all(cves, uems, rcves=[]):2032def load_all(cves, uems, rcves=[]):
2023 table = dict()2033 table = dict()
2024 priority = dict()2034 priority = dict()
@@ -2865,3 +2875,23 @@ def parse_cvss(cvss):
2865 js['baseMetricV3']['exploitabilityScore'] = round(exploitability * 10) / 102875 js['baseMetricV3']['exploitabilityScore'] = round(exploitability * 10) / 10
2866 js['baseMetricV3']['impactScore'] = round(impact * 10) / 102876 js['baseMetricV3']['impactScore'] = round(impact * 10) / 10
2867 return js2877 return js
2878
2879def wordwrap(text, width):
2880 """
2881 A word-wrap function that preserves existing line breaks
2882 and most spaces in the text. Expects that existing line
2883 breaks are posix newlines (\n).
2884 """
2885 return reduce(lambda line, word, width=width:
2886 '%s%s%s' %
2887 (line,
2888 ' \n'[(len(line) - line.rfind('\n') - 1 + len(word.split('\n', 1)[0]) >= width)],
2889 word),
2890 text.split(' ')
2891 )
2892
2893def wrap_text(text, width=75):
2894 """
2895 Wrap text to width chars wide.
2896 """
2897 return wordwrap(text, width).replace(' \n', '\n')
diff --git a/scripts/dup-status-for-pkg b/scripts/dup-status-for-pkg
index fc32055..c15d669 100755
--- a/scripts/dup-status-for-pkg
+++ b/scripts/dup-status-for-pkg
@@ -24,7 +24,7 @@ fi
24for pkg in "$@"; do24for pkg in "$@"; do
25 echo "Duplicating status from ${src} to ${dst} for ${pkg} where was DNE for ${dst}"25 echo "Duplicating status from ${src} to ${dst} for ${pkg} where was DNE for ${dst}"
26 # find files to change26 # find files to change
27 for file in $(grep -l '^'"${dst}_${pkg}"': DNE' active/00boilerplate* active/CVE-* retired/CVE-*); do27 for file in $(grep -l '^'"${dst}_${pkg}"': DNE' active/CVE-* retired/CVE-*); do
28 status=$(grep '^'"${src}_${pkg}"': ' "${file}" | cut -f2- -d' ')28 status=$(grep '^'"${src}_${pkg}"': ' "${file}" | cut -f2- -d' ')
29 if [ ! -z "${status}" ]; then29 if [ ! -z "${status}" ]; then
30 echo "Duplicating status ${status} from ${src} to ${dst} in ${file}"30 echo "Duplicating status ${status} from ${src} to ${dst} in ${file}"
diff --git a/scripts/kernel-triage-missing-break-fix b/scripts/kernel-triage-missing-break-fix
index e60cb38..e21a949 100755
--- a/scripts/kernel-triage-missing-break-fix
+++ b/scripts/kernel-triage-missing-break-fix
@@ -35,7 +35,7 @@ if [ -z "${debian_kernel_cve_tracker}" ] ; then
35 echo35 echo
36fi36fi
3737
38_CVES=$(cd "$UCT" && grep -lr '^Patches_linux:' --exclude '*boilerplate*' active/ | xargs grep -L '^ break-fix:' | sort)38_CVES=$(cd "$UCT" && grep -lr '^Patches_linux:' active/ | xargs grep -L '^ break-fix:' | sort)
39for _CVE in ${_CVES} ; do39for _CVE in ${_CVES} ; do
40 echo "${_CVE}"40 echo "${_CVE}"
41 CVE="${_CVE##active/}"41 CVE="${_CVE##active/}"
diff --git a/scripts/release-cycle-devel-opens b/scripts/release-cycle-devel-opens
index fccd5af..cf08707 100755
--- a/scripts/release-cycle-devel-opens
+++ b/scripts/release-cycle-devel-opens
@@ -18,7 +18,7 @@ if ! [ -d embargoed/ ]; then
18 echo "Unable to find embargoed directory, is it set up?" >&218 echo "Unable to find embargoed directory, is it set up?" >&2
19fi19fi
2020
21for f in active/{CVE-,00boilerplate}* embargoed/CVE-* ; do21for f in active/CVE-* embargoed/CVE-* ; do
22 if egrep -q "^(#?)devel_" "$f" ; then22 if egrep -q "^(#?)devel_" "$f" ; then
23 echo "DEBUG: skipping $f"23 echo "DEBUG: skipping $f"
24 continue24 continue
diff --git a/scripts/release-cycle-released b/scripts/release-cycle-released
index b5cfc7a..c6d844f 100755
--- a/scripts/release-cycle-released
+++ b/scripts/release-cycle-released
@@ -22,7 +22,7 @@ if ! [ -d active/ ]; then
22 exit 222 exit 2
23fi23fi
2424
25for f in active/{00boilerplate,CVE-}*; do25for f in active/CVE-*; do
26 # ignore symlinks so we don't replace twice in the same underlying file26 # ignore symlinks so we don't replace twice in the same underlying file
27 if [ ! -L "$f" ]; then27 if [ ! -L "$f" ]; then
28 perl -pi -e 's/^((#?)devel_(.*))/${2}'"$REL"'_$3\n$1/g' "$f"28 perl -pi -e 's/^((#?)devel_(.*))/${2}'"$REL"'_$3\n$1/g' "$f"
diff --git a/scripts/sync-from-eol.py b/scripts/sync-from-eol.py
index b2a020c..dd6d9eb 100755
--- a/scripts/sync-from-eol.py
+++ b/scripts/sync-from-eol.py
@@ -24,16 +24,12 @@ import sys
24import cve_lib24import cve_lib
25import source_map25import source_map
2626
27import warnings
28warnings.filterwarnings('ignore', 'apt API not stable yet', FutureWarning)
29import apt
3027
31parser = optparse.OptionParser()28parser = optparse.OptionParser()
32parser.add_option("-r", "--release", dest="release", default=None, help="release to modify")29parser.add_option("-r", "--release", dest="release", default=None, help="release to modify")
33parser.add_option("-W", "--whole", dest="whole", help="End of life the whole release", action='store_true')30parser.add_option("-W", "--whole", dest="whole", help="End of life the whole release", action='store_true')
34parser.add_option("-U", "--universe", dest="universe", help="Modify packages in universe and multiverse", action='store_true')31parser.add_option("-U", "--universe", dest="universe", help="Modify packages in universe and multiverse", action='store_true')
35parser.add_option("-u", "--update", dest="update", help="Update CVEs with released package versions", action='store_true')32parser.add_option("-u", "--update", dest="update", help="Update CVEs with released package versions", action='store_true')
36parser.add_option("-b", "--include-boilerplate", help="Update boilerplate files", action='store_true')
37(opt, args) = parser.parse_args()33(opt, args) = parser.parse_args()
3834
39if not opt.release:35if not opt.release:
@@ -52,16 +48,13 @@ pkgs = source_map.load(releases=[opt.release], skip_eol_releases=False)
5248
53cves = glob.glob('%s/CVE-*' % cve_lib.active_dir)49cves = glob.glob('%s/CVE-*' % cve_lib.active_dir)
5450
55if opt.include_boilerplate:
56 cves += glob.glob('%s/00boilerplate.*' % cve_lib.active_dir)
57
58if os.path.islink('embargoed'):51if os.path.islink('embargoed'):
59 cves += glob.glob('embargoed/CVE-*')52 cves += glob.glob('embargoed/CVE-*')
60 cves += glob.glob('embargoed/EMB-*')53 cves += glob.glob('embargoed/EMB-*')
6154
62for filename in cves:55for filename in cves:
63 # we don't want to edit boilerplate symlinks as that will cause them56 # we don't want to edit symlinks as that will cause them to become
64 # to become unsymlinked57 # unsymlinked
65 if os.path.islink(filename):58 if os.path.islink(filename):
66 continue59 continue
6760
@@ -88,17 +81,13 @@ for filename in cves:
88 and cve_lib.is_active_esm_release(cve_lib.get_orig_rel_name(opt.release))81 and cve_lib.is_active_esm_release(cve_lib.get_orig_rel_name(opt.release))
89 ):82 ):
90 status = data['pkgs'][src][opt.release]83 status = data['pkgs'][src][opt.release]
91 if cve.startswith('00boilerplate.'):84 if status[1] != '':
92 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of ESM support')
93 elif status[1] != '':
94 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of ESM support, was %s [%s]' % (status[0], status[1]))85 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of ESM support, was %s [%s]' % (status[0], status[1]))
95 else:86 else:
96 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of ESM support, was %s' % (status[0]))87 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of ESM support, was %s' % (status[0]))
97 elif 'LTS' in cve_lib.release_name(opt.release):88 elif 'LTS' in cve_lib.release_name(opt.release):
98 status = data['pkgs'][src][opt.release]89 status = data['pkgs'][src][opt.release]
99 if cve.startswith('00boilerplate.'):90 if status[1] != '':
100 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of standard support')
101 elif status[1] != '':
102 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of standard support, was %s [%s]' % (status[0], status[1]))91 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of standard support, was %s [%s]' % (status[0], status[1]))
103 else:92 else:
104 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of standard support, was %s' % (status[0]))93 cve_lib.update_state(filename, src, opt.release, 'ignored', 'end of standard support, was %s' % (status[0]))

Subscribers

People subscribed via source and target branches