diff options
author | Scott Garman <scott.a.garman@intel.com> | 2012-01-04 22:30:35 -0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-01-05 11:24:46 +0000 |
commit | 29feb44e05cd2dbdc0724753102574bf4ce12c3f (patch) | |
tree | 70488fe51113886f134682984a560b064ee5017b /meta | |
parent | d34292c0c2a229a597b8a7e24d9d04c1d87396e2 (diff) | |
download | poky-29feb44e05cd2dbdc0724753102574bf4ce12c3f.tar.gz |
insane.bbclass: add QA tests for unsafe references to exec_prefix
Files under exec_prefix (commonly /usr) may not be available during
system recovery. exec_prefix may also be kept on a separate partition
that is mounted late in the boot process.
This QA test throws an warning if a binary in base_[bindir|sbindir|libdir]
is dynamically linked to a file under exec_prefix. The intention is to
turn this into an error in the near future.
It also checks executable non-binaries (e.g, shell scripts) in the above
base directories with a simple grep test to look for references to
exec_prefix. This test only produces a warning, since false positives
are likely.
This fixes [YOCTO #1008]
(From OE-Core rev: 3e9c368a8045044736fc7e348404060498c7491b)
Signed-off-by: Scott Garman <scott.a.garman@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
-rw-r--r-- | meta/classes/insane.bbclass | 111 |
1 files changed, 109 insertions, 2 deletions
diff --git a/meta/classes/insane.bbclass b/meta/classes/insane.bbclass index 5726e69e71..b8d45073ef 100644 --- a/meta/classes/insane.bbclass +++ b/meta/classes/insane.bbclass | |||
@@ -11,6 +11,10 @@ | |||
11 | # -Check if packages contains .debug directories or .so files | 11 | # -Check if packages contains .debug directories or .so files |
12 | # where they should be in -dev or -dbg | 12 | # where they should be in -dev or -dbg |
13 | # -Check if config.log contains traces to broken autoconf tests | 13 | # -Check if config.log contains traces to broken autoconf tests |
14 | # -Ensure that binaries in base_[bindir|sbindir|libdir] do not link | ||
15 | # into exec_prefix | ||
16 | # -Check that scripts in base_[bindir|sbindir|libdir] do not reference | ||
17 | # files under exec_prefix | ||
14 | 18 | ||
15 | 19 | ||
16 | # | 20 | # |
@@ -19,9 +23,14 @@ | |||
19 | # The package.bbclass can help us here. | 23 | # The package.bbclass can help us here. |
20 | # | 24 | # |
21 | inherit package | 25 | inherit package |
22 | PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native" | 26 | PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native ${QADEPENDS}" |
23 | PACKAGEFUNCS += " do_package_qa " | 27 | PACKAGEFUNCS += " do_package_qa " |
24 | 28 | ||
29 | # unsafe-references-in-binaries requires prelink-rtld from | ||
30 | # prelink-native, but we don't want this DEPENDS for -native builds | ||
31 | QADEPENDS = "prelink-native" | ||
32 | QADEPENDS_virtclass-native = "" | ||
33 | QADEPENDS_virtclass-nativesdk = "" | ||
25 | 34 | ||
26 | # | 35 | # |
27 | # dictionary for elf headers | 36 | # dictionary for elf headers |
@@ -100,7 +109,7 @@ def package_qa_get_machine_dict(): | |||
100 | 109 | ||
101 | 110 | ||
102 | # Currently not being used by default "desktop" | 111 | # Currently not being used by default "desktop" |
103 | WARN_QA ?= "ldflags useless-rpaths rpaths" | 112 | WARN_QA ?= "ldflags useless-rpaths rpaths unsafe-references-in-binaries unsafe-references-in-scripts" |
104 | ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch la2 pkgconfig la perms" | 113 | ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch la2 pkgconfig la perms" |
105 | 114 | ||
106 | def package_qa_clean_path(path,d): | 115 | def package_qa_clean_path(path,d): |
@@ -201,6 +210,104 @@ def package_qa_check_perm(path,name,d, elf, messages): | |||
201 | """ | 210 | """ |
202 | return | 211 | return |
203 | 212 | ||
213 | QAPATHTEST[unsafe-references-in-binaries] = "package_qa_check_unsafe_references_in_binaries" | ||
214 | def package_qa_check_unsafe_references_in_binaries(path, name, d, elf, messages): | ||
215 | """ | ||
216 | Ensure binaries in base_[bindir|sbindir|libdir] do not link to files under exec_prefix | ||
217 | """ | ||
218 | if unsafe_references_skippable(path, name, d): | ||
219 | return | ||
220 | |||
221 | if elf: | ||
222 | import subprocess as sub | ||
223 | pn = d.getVar('PN', True) | ||
224 | |||
225 | exec_prefix = d.getVar('exec_prefix', True) | ||
226 | sysroot_path = d.getVar('STAGING_DIR_TARGET', True) | ||
227 | sysroot_path_usr = sysroot_path + exec_prefix | ||
228 | |||
229 | try: | ||
230 | ldd_output = sub.check_output(["prelink-rtld", "--root", sysroot_path, path]) | ||
231 | except sub.CalledProcessError as e: | ||
232 | if e.returncode != 127: | ||
233 | error_msg = pn + ": prelink-rtld aborted when processing %s" % path | ||
234 | package_qa_handle_error("unsafe-references-in-binaries", error_msg, d) | ||
235 | return False | ||
236 | else: | ||
237 | # Sometimes this is done deliberately (e.g, e2fsprogs), so only warn | ||
238 | bb.warn("%s has missing library dependencies" % path) | ||
239 | return | ||
240 | if sysroot_path_usr in ldd_output: | ||
241 | error_msg = pn + ": %s links to something under exec_prefix" % path | ||
242 | package_qa_handle_error("unsafe-references-in-binaries", error_msg, d) | ||
243 | error_msg = "ldd reports: %s" % ldd_output | ||
244 | package_qa_handle_error("unsafe-references-in-binaries", error_msg, d) | ||
245 | return False | ||
246 | |||
247 | QAPATHTEST[unsafe-references-in-scripts] = "package_qa_check_unsafe_references_in_scripts" | ||
248 | def package_qa_check_unsafe_references_in_scripts(path, name, d, elf, messages): | ||
249 | """ | ||
250 | Warn if scripts in base_[bindir|sbindir|libdir] reference files under exec_prefix | ||
251 | """ | ||
252 | if unsafe_references_skippable(path, name, d): | ||
253 | return | ||
254 | |||
255 | if not elf: | ||
256 | import stat | ||
257 | pn = d.getVar('PN', True) | ||
258 | |||
259 | # Ensure we're checking an executable script | ||
260 | statinfo = os.stat(path) | ||
261 | if bool(statinfo.st_mode & stat.S_IXUSR): | ||
262 | # grep shell scripts for possible references to /exec_prefix/ | ||
263 | exec_prefix = d.getVar('exec_prefix', True) | ||
264 | statement = "grep -e '%s/' %s > /dev/null" % (exec_prefix, path) | ||
265 | if os.system(statement) == 0: | ||
266 | error_msg = pn + ": Found a reference to %s/ in %s" % (exec_prefix, path) | ||
267 | package_qa_handle_error("unsafe-references-in-scripts", error_msg, d) | ||
268 | error_msg = "Shell scripts in base_bindir and base_sbindir should not reference anything in exec_prefix" | ||
269 | package_qa_handle_error("unsafe-references-in-scripts", error_msg, d) | ||
270 | |||
271 | def unsafe_references_skippable(path, name, d): | ||
272 | if bb.data.inherits_class('native', d) or bb.data.inherits_class('nativesdk', d): | ||
273 | return True | ||
274 | |||
275 | if "-dbg" in name or "-dev" in name: | ||
276 | return True | ||
277 | |||
278 | # Other package names to skip: | ||
279 | if name.startswith("kernel-module-"): | ||
280 | return True | ||
281 | |||
282 | # Skip symlinks | ||
283 | if os.path.islink(path): | ||
284 | return True | ||
285 | |||
286 | # Skip unusual rootfs layouts which make these tests irrelevant | ||
287 | exec_prefix = d.getVar('exec_prefix', True) | ||
288 | if exec_prefix == "": | ||
289 | return True | ||
290 | |||
291 | pkgdest = d.getVar('PKGDEST', True) | ||
292 | pkgdest = pkgdest + "/" + name | ||
293 | pkgdest = os.path.abspath(pkgdest) | ||
294 | base_bindir = pkgdest + d.getVar('base_bindir', True) | ||
295 | base_sbindir = pkgdest + d.getVar('base_sbindir', True) | ||
296 | base_libdir = pkgdest + d.getVar('base_libdir', True) | ||
297 | bindir = pkgdest + d.getVar('bindir', True) | ||
298 | sbindir = pkgdest + d.getVar('sbindir', True) | ||
299 | libdir = pkgdest + d.getVar('libdir', True) | ||
300 | |||
301 | if base_bindir == bindir and base_sbindir == sbindir and base_libdir == libdir: | ||
302 | return True | ||
303 | |||
304 | # Skip files not in base_[bindir|sbindir|libdir] | ||
305 | path = os.path.abspath(path) | ||
306 | if not (base_bindir in path or base_sbindir in path or base_libdir in path): | ||
307 | return True | ||
308 | |||
309 | return False | ||
310 | |||
204 | QAPATHTEST[arch] = "package_qa_check_arch" | 311 | QAPATHTEST[arch] = "package_qa_check_arch" |
205 | def package_qa_check_arch(path,name,d, elf, messages): | 312 | def package_qa_check_arch(path,name,d, elf, messages): |
206 | """ | 313 | """ |