From 9c529bb6fca12e63f8a5eca2bd5db10782b1960b Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Thu, 25 Feb 2016 21:19:26 -0800 Subject: [PATCH] check_root: add test for missing interpreters --- build_library/build_image_util.sh | 3 +++ build_library/check_root | 40 +++++++++++++++++++++++++++++ build_library/test_image_content.sh | 9 +++++++ 3 files changed, 52 insertions(+) diff --git a/build_library/build_image_util.sh b/build_library/build_image_util.sh index 3dc817d8e1..6f827cc4e6 100755 --- a/build_library/build_image_util.sh +++ b/build_library/build_image_util.sh @@ -122,6 +122,9 @@ emerge_to_image() { PORTAGE_CONFIGROOT="${BUILD_DIR}"/configroot \ emerge --root-deps=rdeps --usepkgonly --jobs=$FLAGS_jobs -v "$@" + # Shortcut if this was just baselayout + [[ "$*" == *sys-apps/baselayout ]] && return + # Make sure profile.env has been generated sudo -E ROOT="${root_fs_dir}" env-update --no-ldconfig diff --git a/build_library/check_root b/build_library/check_root index ad5f83d7a9..d2b6e3dd95 100755 --- a/build_library/check_root +++ b/build_library/check_root @@ -6,6 +6,9 @@ from __future__ import unicode_literals +import fnmatch +import os +import stat import sys import portage @@ -72,6 +75,13 @@ IGNORE_MISSING = { USR_LINKS = ("/bin/", "/sbin/", "/lib/", "/lib32/", "/lib64/") +IGNORE_SHEBANG = ( + b"*/python2.7/cgi.py", + b"*/usr/lib64/modules/*/source/scripts/*", + b"*/usr/share/nova-agent/*/etc/gentoo/nova-agent", + b"*/tmp/*", +) + def provided_sonames(): for cpv in VARDB.cpv_all(): raw = VARDB.aux_get(cpv, ["PROVIDES"])[0] @@ -147,6 +157,35 @@ def check_usr(): ok = False return ok +def is_exe(path): + # just check other, assuming root or group only commands are not scripts. + perms = stat.S_IROTH|stat.S_IXOTH + mode = os.lstat(path).st_mode + return stat.S_ISREG(mode) and mode&perms == perms + +def check_shebang(): + ok = True + cache = {} + root = os.environ.get("ROOT", b"/") + for parent, _, files in os.walk(root): + for path in [os.path.join(parent, f) for f in files]: + if any(fnmatch.fnmatchcase(path,i) for i in IGNORE_SHEBANG): + continue + if not is_exe(path): + continue + with open(path, "r") as fd: + line = fd.readline(80) + if not line.startswith(b"#!"): + continue + cmd = line[2:].rstrip().split(None,1)[0] + if cmd not in cache: + cache[cmd] = os.path.exists(root+cmd) + if not cache[cmd]: + relpath = path[len(root):] + error("%s: %s does not exist", relpath, cmd) + ok = False + return ok + def error(fmt, *args): sys.stderr.write(output.red(fmt % args)) sys.stderr.write("\n") @@ -156,6 +195,7 @@ def main(): check_funcs = { "libs": check_libs, "usr": check_usr, + "shebang": check_shebang, } if not sys.stderr.isatty(): diff --git a/build_library/test_image_content.sh b/build_library/test_image_content.sh index e1856f0d60..4a28f3d4ff 100644 --- a/build_library/test_image_content.sh +++ b/build_library/test_image_content.sh @@ -36,5 +36,14 @@ test_image_content() { returncode=1 fi + # Check that there are no #! lines pointing to non-existant locations + if ! ROOT="$root" "$check_root" shebang; then + warn "test_image_content: Failed #! check" + # Only a warning for now. We still have to actually remove all of the + # offending scripts. + #error "test_image_content: Failed #! check" + #returncode=1 + fi + return $returncode }