summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oe/cve_check.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py
index b17390de90..a4b831831b 100644
--- a/meta/lib/oe/cve_check.py
+++ b/meta/lib/oe/cve_check.py
@@ -89,3 +89,85 @@ def update_symlinks(target_path, link_path):
89 if os.path.exists(os.path.realpath(link_path)): 89 if os.path.exists(os.path.realpath(link_path)):
90 os.remove(link_path) 90 os.remove(link_path)
91 os.symlink(os.path.basename(target_path), link_path) 91 os.symlink(os.path.basename(target_path), link_path)
92
93def get_patched_cves(d):
94 """
95 Get patches that solve CVEs using the "CVE: " tag.
96 """
97
98 import re
99 import oe.patch
100
101 pn = d.getVar("PN")
102 cve_match = re.compile("CVE:( CVE\-\d{4}\-\d+)+")
103
104 # Matches the last "CVE-YYYY-ID" in the file name, also if written
105 # in lowercase. Possible to have multiple CVE IDs in a single
106 # file name, but only the last one will be detected from the file name.
107 # However, patch files contents addressing multiple CVE IDs are supported
108 # (cve_match regular expression)
109
110 cve_file_name_match = re.compile(".*([Cc][Vv][Ee]\-\d{4}\-\d+)")
111
112 patched_cves = set()
113 bb.debug(2, "Looking for patches that solves CVEs for %s" % pn)
114 for url in oe.patch.src_patches(d):
115 patch_file = bb.fetch.decodeurl(url)[2]
116
117 if not os.path.isfile(patch_file):
118 bb.error("File Not found: %s" % patch_file)
119 raise FileNotFoundError
120
121 # Check patch file name for CVE ID
122 fname_match = cve_file_name_match.search(patch_file)
123 if fname_match:
124 cve = fname_match.group(1).upper()
125 patched_cves.add(cve)
126 bb.debug(2, "Found CVE %s from patch file name %s" % (cve, patch_file))
127
128 with open(patch_file, "r", encoding="utf-8") as f:
129 try:
130 patch_text = f.read()
131 except UnicodeDecodeError:
132 bb.debug(1, "Failed to read patch %s using UTF-8 encoding"
133 " trying with iso8859-1" % patch_file)
134 f.close()
135 with open(patch_file, "r", encoding="iso8859-1") as f:
136 patch_text = f.read()
137
138 # Search for one or more "CVE: " lines
139 text_match = False
140 for match in cve_match.finditer(patch_text):
141 # Get only the CVEs without the "CVE: " tag
142 cves = patch_text[match.start()+5:match.end()]
143 for cve in cves.split():
144 bb.debug(2, "Patch %s solves %s" % (patch_file, cve))
145 patched_cves.add(cve)
146 text_match = True
147
148 if not fname_match and not text_match:
149 bb.debug(2, "Patch %s doesn't solve CVEs" % patch_file)
150
151 return patched_cves
152
153
154def get_cpe_ids(cve_product, version):
155 """
156 Get list of CPE identifiers for the given product and version
157 """
158
159 version = version.split("+git")[0]
160
161 cpe_ids = []
162 for product in cve_product.split():
163 # CVE_PRODUCT in recipes may include vendor information for CPE identifiers. If not,
164 # use wildcard for vendor.
165 if ":" in product:
166 vendor, product = product.split(":", 1)
167 else:
168 vendor = "*"
169
170 cpe_id = f'cpe:2.3:a:{vendor}:{product}:{version}:*:*:*:*:*:*:*'
171 cpe_ids.append(cpe_id)
172
173 return cpe_ids