Merge ~alexmurray/ubuntu-cve-tracker:check-syntax-support-for-kernel-patches into ubuntu-cve-tracker:master

Proposed by Alex Murray
Status: Merged
Merged at revision: 09d9db546cb44ac19c999a34cf41e2a1b2f5a8cc
Proposed branch: ~alexmurray/ubuntu-cve-tracker:check-syntax-support-for-kernel-patches
Merge into: ubuntu-cve-tracker:master
Diff against target: 456 lines (+162/-97) (has conflicts)
15 files modified
active/CVE-2021-46904 (+1/-0)
active/CVE-2021-46905 (+1/-0)
active/CVE-2022-48626 (+1/-0)
active/CVE-2023-52469 (+1/-0)
active/CVE-2024-26602 (+4/-0)
ignored/CVE-2019-12379 (+1/-0)
ignored/CVE-2019-12454 (+1/-0)
ignored/CVE-2022-3642 (+1/-0)
ignored/CVE-2023-35825 (+1/-0)
retired/CVE-2008-1375 (+1/-0)
retired/CVE-2019-12455 (+2/-1)
retired/CVE-2021-3542 (+1/-0)
scripts/active_edit (+2/-96)
scripts/check-syntax (+32/-0)
scripts/cve_lib.py (+112/-0)
Conflict in active/CVE-2024-26602
Reviewer Review Type Date Requested Status
Marc Deslauriers Approve
Review via email: mp+461311@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Seth Arnold (seth-arnold) wrote :

A few random comments throughout; I realize some are against the previous version, but it's better late than never...

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

This will likely be easier to review by looking at the individual commits.

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

Thanks Seth - I've added some extra changes for the regex precompilation etc, and tried to address your other comments too.

Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

The commits look good! Now that I think about it, I agree that putting it in check-syntax and only applying it if there is no break-fix is the right approach.

The only thing that may need changing in the future is:

+ assert commit_hash is not None
+

I'd probably just "return []" there so that a bad upstream patch for some reason wouldn't break our triage, but I think that's unlikely to ever happen.

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

Thanks Marc - good point, I made it print an error as well in that case.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/active/CVE-2021-46904 b/active/CVE-2021-46904
2index f19d00f..72c1b40 100644
3--- a/active/CVE-2021-46904
4+++ b/active/CVE-2021-46904
5@@ -15,6 +15,7 @@ Assigned-to:
6 CVSS:
7
8 Patches_linux:
9+ break-fix: 72dc1c096c7051a48ab1dbb12f71976656b55eb5 8a12f8836145ffe37e9c8733dce18c22fb668b66
10 upstream_linux: needs-triage
11 trusty_linux: ignored (end of standard support)
12 trusty/esm_linux: needs-triage
13diff --git a/active/CVE-2021-46905 b/active/CVE-2021-46905
14index c1b64e9..c422718 100644
15--- a/active/CVE-2021-46905
16+++ b/active/CVE-2021-46905
17@@ -15,6 +15,7 @@ Assigned-to:
18 CVSS:
19
20 Patches_linux:
21+ break-fix: 8a12f8836145ffe37e9c8733dce18c22fb668b66 2ad5692db72874f02b9ad551d26345437ea4f7f3
22 upstream_linux: not-affected (debian: No Debian released version vulnerable)
23 trusty_linux: ignored (end of standard support)
24 trusty/esm_linux: needs-triage
25diff --git a/active/CVE-2022-48626 b/active/CVE-2022-48626
26index dc2d16c..76d45c6 100644
27--- a/active/CVE-2022-48626
28+++ b/active/CVE-2022-48626
29@@ -15,6 +15,7 @@ Assigned-to:
30 CVSS:
31
32 Patches_linux:
33+ break-fix: - bd2db32e7c3e35bd4d9b8bbff689434a50893546
34 upstream_linux: needs-triage
35 trusty_linux: ignored (end of standard support)
36 trusty/esm_linux: needs-triage
37diff --git a/active/CVE-2023-52469 b/active/CVE-2023-52469
38index 5d4154b..f4d8a33 100644
39--- a/active/CVE-2023-52469
40+++ b/active/CVE-2023-52469
41@@ -17,6 +17,7 @@ Assigned-to:
42 CVSS:
43
44 Patches_linux:
45+ break-fix: a2e73f56fa6282481927ec43aa9362c03c2e2104 28dd788382c43b330480f57cd34cde0840896743
46 upstream_linux: needs-triage
47 trusty_linux: ignored (end of standard support)
48 trusty/esm_linux: needs-triage
49diff --git a/active/CVE-2024-26602 b/active/CVE-2024-26602
50index b7e01d9..630af59 100644
51--- a/active/CVE-2024-26602
52+++ b/active/CVE-2024-26602
53@@ -15,6 +15,10 @@ Assigned-to:
54 CVSS:
55
56 Patches_linux:
57+<<<<<<< active/CVE-2024-26602
58+=======
59+ break-fix: 22e4ebb975822833b083533035233d128b30e98f 944d5fe50f3f03daacfea16300e656a1691c4a23
60+>>>>>>> active/CVE-2024-26602
61 break-fix: c5f58bd58f432be5d92df33c5458e0bcbee3aadf 944d5fe50f3f03daacfea16300e656a1691c4a23
62 upstream_linux: needs-triage
63 trusty_linux: ignored (end of standard support)
64diff --git a/ignored/CVE-2019-12379 b/ignored/CVE-2019-12379
65index a4f7043..8dd5d99 100644
66--- a/ignored/CVE-2019-12379
67+++ b/ignored/CVE-2019-12379
68@@ -21,6 +21,7 @@ CVSS:
69 nvd: CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H [5.5 MEDIUM]
70
71 Patches_linux:
72+ break-fix: - 84ecc2f6eb1cb12e6d44818f94fa49b50f06e6ac
73 upstream_linux: ignored (not an issue)
74 precise/esm_linux: ignored (end of life, was needs-triage)
75 trusty_linux: ignored (end of standard support)
76diff --git a/ignored/CVE-2019-12454 b/ignored/CVE-2019-12454
77index b77df14..ec5441e 100644
78--- a/ignored/CVE-2019-12454
79+++ b/ignored/CVE-2019-12454
80@@ -24,6 +24,7 @@ CVSS:
81 nvd: CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H [7.8 HIGH]
82
83 Patches_linux:
84+ break-fix: - a54988113985ca22e414e132054f234fc8a92604
85 upstream_linux: not-affected (debian: Vulnerable code not present, introduced in 5.1-rc1)
86 precise/esm_linux: ignored (end of life, was needs-triage)
87 trusty_linux: ignored (end of standard support)
88diff --git a/ignored/CVE-2022-3642 b/ignored/CVE-2022-3642
89index 5d2904a..f3cf007 100644
90--- a/ignored/CVE-2022-3642
91+++ b/ignored/CVE-2022-3642
92@@ -19,6 +19,7 @@ CVSS:
93 nvd: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N [5.5 MEDIUM]
94
95 Patches_linux:
96+ break-fix: c888183b21f36a247bb166ca9365705611bea847 80e5acb6dd72b25a6e6527443b9e9c1c3a7bcef6
97 upstream_linux: not-affected (debian: only wireless-next)
98 esm-infra/xenial_linux: needs-triage
99 trusty_linux: ignored (end of standard support)
100diff --git a/ignored/CVE-2023-35825 b/ignored/CVE-2023-35825
101index ff67bb5..6e42c4e 100644
102--- a/ignored/CVE-2023-35825
103+++ b/ignored/CVE-2023-35825
104@@ -23,6 +23,7 @@ Assigned-to:
105 CVSS:
106
107 Patches_linux:
108+ break-fix: - 63264422785021704c39b38f65a78ab9e4a186d7
109 upstream_linux: released (6.3.7-1)
110 trusty_linux: ignored (end of standard support)
111 trusty/esm_linux: needs-triage
112diff --git a/retired/CVE-2008-1375 b/retired/CVE-2008-1375
113index cfacb91..87c677d 100644
114--- a/retired/CVE-2008-1375
115+++ b/retired/CVE-2008-1375
116@@ -46,6 +46,7 @@ hardy_linux-source-2.6.22: DNE
117 devel_linux-source-2.6.22: DNE
118
119 Patches_linux:
120+ break-fix: - 214b7049a7929f03bbd2786aaef04b8b79db34e2
121 upstream_linux: pending (2.6.26-rc1)
122 dapper_linux: DNE
123 feisty_linux: DNE
124diff --git a/retired/CVE-2019-12455 b/retired/CVE-2019-12455
125index 61a8e7e..397354f 100644
126--- a/retired/CVE-2019-12455
127+++ b/retired/CVE-2019-12455
128@@ -2,7 +2,7 @@ Candidate: CVE-2019-12455
129 PublicDate: 2019-05-30 04:29:00 UTC
130 References:
131 https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-12455
132- https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git/commit/?h=sunxi/clk-for-5.3&id=fcdf445ff42f036d22178b49cf64e92d527c1330
133+ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=fcdf445ff42f036d22178b49cf64e92d527c1330
134 https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg2010240.html
135 Description:
136 ** DISPUTED ** An issue was discovered in sunxi_divs_clk_setup in
137@@ -28,6 +28,7 @@ CVSS:
138 nvd: CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H [5.5 MEDIUM]
139
140 Patches_linux:
141+ break-fix: - fcdf445ff42f036d22178b49cf64e92d527c1330
142 upstream_linux: needed
143 precise/esm_linux: ignored (end of life, was needs-triage)
144 trusty_linux: ignored (end of standard support)
145diff --git a/retired/CVE-2021-3542 b/retired/CVE-2021-3542
146index d24b901..f916d9b 100644
147--- a/retired/CVE-2021-3542
148+++ b/retired/CVE-2021-3542
149@@ -23,6 +23,7 @@ Assigned-to:
150 CVSS:
151
152 Patches_linux:
153+ break-fix: - 35d2969ea3c7d32aee78066b1f3cf61a0d935a4e
154 upstream_linux: not-affected
155 trusty_linux: ignored (end of standard support)
156 trusty/esm_linux: not-affected
157diff --git a/scripts/active_edit b/scripts/active_edit
158index dadaf35..d71f0b3 100755
159--- a/scripts/active_edit
160+++ b/scripts/active_edit
161@@ -14,7 +14,6 @@ import os
162 import pathlib
163 import re
164 import sys
165-import urllib.request
166
167 import cve_lib
168 import source_map
169@@ -72,99 +71,6 @@ def release_wants_dne(release):
170 _, product, _, _ = cve_lib.get_subproject_details(release)
171 return product != None and product == cve_lib.PRODUCT_UBUNTU
172
173-def fetch_kernel_fixes(url):
174- '''Downloads a kernel commit and returns a list of break-fixes'''
175- commit_hash = None
176- fixes = []
177-
178- # Strip off comment at the end
179- if ' ' in url:
180- url = url.split(' ')[0]
181-
182- # Short URL, turn it into long one
183- if url.startswith('https://git.kernel.org/linus/'):
184- url = url.replace('https://git.kernel.org/linus/',
185- 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=')
186- if url.startswith('https://git.kernel.org/stable/c/'):
187- url = url.replace('https://git.kernel.org/stable/c/',
188- 'https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=')
189-
190- # Get the raw patch
191- url = url.replace('/commit/', '/patch/')
192-
193- with urllib.request.urlopen(url) as response:
194- patch = response.read().decode('utf-8')
195-
196- for line in patch.split("\n"):
197- if re.match("commit [0-9a-f]{40} upstream.", line):
198- # This is an LTS backport, skip it
199- return []
200- if re.match("\[ Upstream commit [0-9a-f]{40} \]", line):
201- # This is an LTS backport, skip it
202- return []
203- if not commit_hash and line.startswith("From "):
204- commit_hash = line.split(' ')[1]
205- continue
206- elif line.startswith("Fixes: "):
207- fix_hash = line.split(' ')[1]
208- fixes.append([fix_hash, commit_hash])
209-
210- # If we didn't find a Fixes tag, just use -
211- if fixes == []:
212- fixes.append(['-', commit_hash])
213-
214- return fixes
215-
216-def in_break_fixes(commit, break_fixes):
217- '''See if a commit is in the hash_list'''
218- # properly handle comparing short and long hashes
219- for [break_hash,fix_hash] in break_fixes:
220- if commit.startswith(break_hash):
221- return True
222- if break_hash.startswith(commit):
223- return True
224- return False
225-
226-def get_long_kernel_hash(short_hash):
227- '''Attempts to get a long kernel hash'''
228-
229- url = 'https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/patch/?id=' + short_hash
230- with urllib.request.urlopen(url) as response:
231- patch = response.read().decode('utf-8')
232-
233- for line in patch.split("\n"):
234- if line.startswith("From "):
235- commit_hash = line.split(' ')[1]
236- if commit_hash.startswith(short_hash):
237- return commit_hash
238-
239- return short_hash
240-
241-
242-def validate_kernel_fixes(break_fixes):
243- '''Validate list of break-fixes'''
244-
245- if break_fixes == []:
246- return []
247-
248- # Make sure a breaks URL wasn't listed in the URLs by mistake
249- validated = []
250- for [break_hash,fix_hash] in break_fixes:
251- # Don't check this for now, it can result in false positives
252- #if not in_break_fixes(fix_hash, break_fixes):
253- if True:
254- if break_hash != '-' and len(break_hash) < 40:
255- break_hash = get_long_kernel_hash(break_hash)
256- # Make sure it's not a dupe
257- dupe = False
258- for [v_break_hash,v_fix_hash] in validated:
259- if break_hash == v_break_hash and fix_hash == v_fix_hash:
260- dupe = True
261- if not dupe:
262- validated.append([break_hash, fix_hash])
263-
264- return validated
265-
266 def _add_pkg(p, fp, fixed, parent, embargoed, break_fixes):
267 print('', file=fp)
268 print('Patches_%s:' % p, file=fp)
269@@ -291,8 +197,8 @@ def create_or_update_cve(cve, packages, priority=None, bug_urls=None,
270 url.startswith('https://git.kernel.org/stable/c/') or
271 url.startswith('https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=') or
272 url.startswith('https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=')):
273- break_fixes += fetch_kernel_fixes(url)
274- break_fixes = validate_kernel_fixes(break_fixes)
275+ break_fixes += cve_lib.fetch_kernel_fixes(url)
276+ break_fixes = cve_lib.validate_kernel_fixes(break_fixes)
277
278 # collect notes from pkg_db and add any extra pkgs from pkg_db as well
279 notes = []
280diff --git a/scripts/check-syntax b/scripts/check-syntax
281index e5c909f..f89a0e4 100755
282--- a/scripts/check-syntax
283+++ b/scripts/check-syntax
284@@ -475,6 +475,19 @@ def fixup_entry_wrong(filename, pkg, rel):
285
286 cve_lib.update_state(filename, pkg, rel, status, None)
287
288+def fixup_entry_missing_break_fix(filename, pkg, ref):
289+ urls = cve_lib.fetch_kernel_fixes(ref)
290+ urls = cve_lib.validate_kernel_fixes(urls)
291+
292+ for url in urls:
293+ # convert to the break-fix format as a string
294+ url = " ".join(url)
295+ if opt.dry_run:
296+ print("Dry-Run: adding break-fix %s, %s, to %s" % (filename, pkg, url))
297+ return
298+
299+ cve_lib.add_patch(filename, pkg, url, "break-fix")
300+
301 def get_cve_path(cve, rel):
302
303 cve = os.path.basename(cve)
304@@ -1132,6 +1145,25 @@ def check_cve(cve):
305 )
306 cve_okay = False
307
308+ # if there is a reference URL to a kernel commit then check there is a
309+ # break-fix entry against the linux package
310+ if "References" in data:
311+ for ref in data["References"].split("\n"):
312+ if "git.kernel.org" in ref:
313+ # the CVE needs to already be triaged against linux and hence
314+ # have a patches entry for it
315+ if "linux" in data["patches"] and len(data["patches"]["linux"]) == 0:
316+ filename = srcmap["References"][0] if "References" in srcmap else cvepath
317+ linenum = srcmap["References"][1] if "References" in srcmap else 1
318+ print(
319+ "%s: %d: missing break-fix entry for kernel commit"
320+ % (filename, linenum),
321+ file=sys.stderr,
322+ )
323+ cve_okay = False
324+ if opt.autofix:
325+ fixup_entry_missing_break_fix(filename, "linux", ref)
326+
327 for entry in data["CVSS"]:
328 srcname = entry['source']
329 filename = srcmap["CVSS"][srcname][0]
330diff --git a/scripts/cve_lib.py b/scripts/cve_lib.py
331index c97cae6..416d5f7 100755
332--- a/scripts/cve_lib.py
333+++ b/scripts/cve_lib.py
334@@ -22,6 +22,8 @@ import time
335 import cache_urllib
336 import json
337 import yaml
338+import urllib.error
339+import urllib.request
340
341 from functools import reduce
342
343@@ -3456,3 +3458,113 @@ def wrap_text(text, width=75):
344 Wrap text to width chars wide.
345 """
346 return wordwrap(text, width).replace(' \n', '\n')
347+
348+def fetch_kernel_fixes(url):
349+ '''Downloads a kernel commit and returns a list of break-fixes'''
350+ commit_hash = None
351+ fixes = []
352+
353+ # Strip off comment at the end
354+ if ' ' in url:
355+ url = url.split(' ')[0]
356+
357+ # Short URL, turn it into long one
358+ if url.startswith('https://git.kernel.org/linus/'):
359+ url = url.replace('https://git.kernel.org/linus/',
360+ 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=')
361+ if url.startswith('https://git.kernel.org/stable/c/'):
362+ url = url.replace('https://git.kernel.org/stable/c/',
363+ 'https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=')
364+ # old URL style - replace to be more modern
365+ if url.startswith('http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h='):
366+ url = url.replace('http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=',
367+ 'https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=')
368+
369+ # Get the raw patch
370+ url = url.replace('/commit/', '/patch/')
371+
372+ try:
373+ with urllib.request.urlopen(url) as response:
374+ patch = response.read().decode('utf-8')
375+ except urllib.error.HTTPError as e:
376+ print("WARNING: Failed to fetch patch URL %s: %s" % (url, str(e)), file=sys.stderr)
377+ return fixes
378+
379+ backport_re = re.compile(r"(commit [0-9a-f]{40} upstream.|\[ Upstream commit [0-9a-f]{40} \])")
380+ for line in patch.split("\n"):
381+ # stop early if we have reached the main patch body
382+ if line.startswith("---"):
383+ break
384+ if backport_re.match(line):
385+ # This is an LTS backport, skip it
386+ return []
387+ if not commit_hash and line.startswith("From "):
388+ commit_hash = line.split(' ')[1]
389+ continue
390+ elif line.startswith("Fixes: "):
391+ fix_hash = line.split(' ')[1]
392+ fixes.append([fix_hash, commit_hash])
393+
394+ if commit_hash is None:
395+ print("Failed to get commit hash from %s" % url, file=sys.stderr)
396+ return []
397+
398+ # If we didn't find a Fixes tag, just use -
399+ if fixes == []:
400+ fixes.append(['-', commit_hash])
401+
402+ return fixes
403+
404+def in_break_fixes(commit, break_fixes):
405+ '''See if a commit is in the hash_list'''
406+ # properly handle comparing short and long hashes
407+ for [break_hash,fix_hash] in break_fixes:
408+ if commit.startswith(break_hash):
409+ return True
410+ if break_hash.startswith(commit):
411+ return True
412+ return False
413+
414+def get_long_kernel_hash(short_hash):
415+ '''Attempts to get a long kernel hash'''
416+
417+ url = 'https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/patch/?id=' + short_hash
418+ with urllib.request.urlopen(url) as response:
419+ patch = response.read().decode('utf-8')
420+
421+ for line in patch.split("\n"):
422+ if line.startswith("From "):
423+ commit_hash = line.split(' ')[1]
424+ if commit_hash.startswith(short_hash):
425+ return commit_hash
426+
427+ return short_hash
428+
429+
430+def validate_kernel_fixes(break_fixes):
431+ '''Validate list of break-fixes'''
432+
433+ if break_fixes == []:
434+ return []
435+
436+ # Make sure a breaks URL wasn't listed in the URLs by mistake
437+ validated = []
438+ for [break_hash,fix_hash] in break_fixes:
439+ # Don't check this for now, it can result in false positives
440+ #if not in_break_fixes(fix_hash, break_fixes):
441+ if True:
442+ if break_hash is None or fix_hash is None:
443+ continue
444+ if break_hash != '-' and len(break_hash) < 40:
445+ break_hash = get_long_kernel_hash(break_hash)
446+ # Make sure it's not a dupe
447+ dupe = False
448+ for [v_break_hash,v_fix_hash] in validated:
449+ if break_hash == v_break_hash and fix_hash == v_fix_hash:
450+ dupe = True
451+ if not dupe:
452+ validated.append([break_hash, fix_hash])
453+
454+ return validated
455+
456+

Subscribers

People subscribed via source and target branches