mirror of
https://git.yoctoproject.org/poky
synced 2026-04-05 08:02:25 +02:00
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>
This commit is contained in:
committed by
Richard Purdie
parent
d34292c0c2
commit
29feb44e05
@@ -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):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user