[OE-core] [PATCH 7/7] insane.bbclass: add QA tests for unsafe references to exec_prefix

Scott Garman scott.a.garman at intel.com
Wed Jan 4 03:56:57 UTC 2012


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]

Signed-off-by: Scott Garman <scott.a.garman at intel.com>
---
 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 5726e69..b8d4507 100644
--- a/meta/classes/insane.bbclass
+++ b/meta/classes/insane.bbclass
@@ -11,6 +11,10 @@
 #  -Check if packages contains .debug directories or .so files
 #   where they should be in -dev or -dbg
 #  -Check if config.log contains traces to broken autoconf tests
+#  -Ensure that binaries in base_[bindir|sbindir|libdir] do not link
+#   into exec_prefix
+#  -Check that scripts in base_[bindir|sbindir|libdir] do not reference
+#   files under exec_prefix
 
 
 #
@@ -19,9 +23,14 @@
 # The package.bbclass can help us here.
 #
 inherit package
-PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native"
+PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native ${QADEPENDS}"
 PACKAGEFUNCS += " do_package_qa "
 
+# unsafe-references-in-binaries requires prelink-rtld from
+# prelink-native, but we don't want this DEPENDS for -native builds
+QADEPENDS = "prelink-native"
+QADEPENDS_virtclass-native = ""
+QADEPENDS_virtclass-nativesdk = ""
 
 #
 # dictionary for elf headers
@@ -100,7 +109,7 @@ def package_qa_get_machine_dict():
 
 
 # Currently not being used by default "desktop"
-WARN_QA ?= "ldflags useless-rpaths rpaths"
+WARN_QA ?= "ldflags useless-rpaths rpaths unsafe-references-in-binaries unsafe-references-in-scripts"
 ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch la2 pkgconfig la perms"
 
 def package_qa_clean_path(path,d):
@@ -201,6 +210,104 @@ def package_qa_check_perm(path,name,d, elf, messages):
     """
     return
 
+QAPATHTEST[unsafe-references-in-binaries] = "package_qa_check_unsafe_references_in_binaries"
+def package_qa_check_unsafe_references_in_binaries(path, name, d, elf, messages):
+	"""
+	Ensure binaries in base_[bindir|sbindir|libdir] do not link to files under exec_prefix
+	"""
+	if unsafe_references_skippable(path, name, d):
+		return
+
+	if elf:
+		import subprocess as sub
+		pn = d.getVar('PN', True)
+
+		exec_prefix = d.getVar('exec_prefix', True)
+		sysroot_path = d.getVar('STAGING_DIR_TARGET', True)
+		sysroot_path_usr = sysroot_path + exec_prefix
+
+		try:
+			ldd_output = sub.check_output(["prelink-rtld", "--root", sysroot_path, path])
+		except sub.CalledProcessError as e:
+			if e.returncode != 127:
+				error_msg = pn + ": prelink-rtld aborted when processing %s" % path
+				package_qa_handle_error("unsafe-references-in-binaries", error_msg, d)
+				return False
+			else:
+				# Sometimes this is done deliberately (e.g, e2fsprogs), so only warn
+				bb.warn("%s has missing library dependencies" % path)
+				return
+		if sysroot_path_usr in ldd_output:
+			error_msg = pn + ": %s links to something under exec_prefix" % path
+			package_qa_handle_error("unsafe-references-in-binaries", error_msg, d)
+			error_msg = "ldd reports: %s" % ldd_output
+			package_qa_handle_error("unsafe-references-in-binaries", error_msg, d)
+			return False
+
+QAPATHTEST[unsafe-references-in-scripts] = "package_qa_check_unsafe_references_in_scripts"
+def package_qa_check_unsafe_references_in_scripts(path, name, d, elf, messages):
+	"""
+	Warn if scripts in base_[bindir|sbindir|libdir] reference files under exec_prefix
+	"""
+	if unsafe_references_skippable(path, name, d):
+		return
+
+	if not elf:
+		import stat
+		pn = d.getVar('PN', True)
+
+		# Ensure we're checking an executable script
+		statinfo = os.stat(path)
+		if bool(statinfo.st_mode & stat.S_IXUSR):
+			# grep shell scripts for possible references to /exec_prefix/
+			exec_prefix = d.getVar('exec_prefix', True)
+			statement = "grep -e '%s/' %s > /dev/null" % (exec_prefix, path)
+			if os.system(statement) == 0:
+				error_msg = pn + ": Found a reference to %s/ in %s" % (exec_prefix, path)
+				package_qa_handle_error("unsafe-references-in-scripts", error_msg, d)
+				error_msg = "Shell scripts in base_bindir and base_sbindir should not reference anything in exec_prefix"
+				package_qa_handle_error("unsafe-references-in-scripts", error_msg, d)
+
+def unsafe_references_skippable(path, name, d):
+	if bb.data.inherits_class('native', d) or bb.data.inherits_class('nativesdk', d):
+		return True
+
+	if "-dbg" in name or "-dev" in name:
+		return True
+
+	# Other package names to skip:
+	if name.startswith("kernel-module-"):
+		return True
+
+	# Skip symlinks
+	if os.path.islink(path):
+		return True
+
+	# Skip unusual rootfs layouts which make these tests irrelevant
+	exec_prefix = d.getVar('exec_prefix', True)
+	if exec_prefix == "":
+		return True
+
+	pkgdest = d.getVar('PKGDEST', True)
+	pkgdest = pkgdest + "/" + name
+	pkgdest = os.path.abspath(pkgdest)
+	base_bindir = pkgdest + d.getVar('base_bindir', True)
+	base_sbindir = pkgdest + d.getVar('base_sbindir', True)
+	base_libdir = pkgdest + d.getVar('base_libdir', True)
+	bindir = pkgdest + d.getVar('bindir', True)
+	sbindir = pkgdest + d.getVar('sbindir', True)
+	libdir = pkgdest + d.getVar('libdir', True)
+
+	if base_bindir == bindir and base_sbindir == sbindir and base_libdir == libdir:
+		return True
+
+	# Skip files not in base_[bindir|sbindir|libdir]
+	path = os.path.abspath(path)
+	if not (base_bindir in path or base_sbindir in path or base_libdir in path):
+		return True
+
+	return False
+
 QAPATHTEST[arch] = "package_qa_check_arch"
 def package_qa_check_arch(path,name,d, elf, messages):
     """
-- 
1.7.5.4





More information about the Openembedded-core mailing list