mirror of
https://github.com/flatcar/scripts.git
synced 2026-05-04 19:56:32 +02:00
Merge pull request #642 from euank/symlink-checker
check_root: add check for broken symlinks
This commit is contained in:
commit
18076b8bdb
@ -84,6 +84,22 @@ IGNORE_SHEBANG = (
|
||||
b"*/doc/*",
|
||||
)
|
||||
|
||||
IGNORE_SYMLINK = (
|
||||
# symlinks to sdk chroot
|
||||
b"/build/*",
|
||||
b"/var/tmp/portage/*",
|
||||
b"/etc/portage/*",
|
||||
|
||||
# symlinks to /run
|
||||
b"/usr/share/baselayout/motd",
|
||||
b"/etc/issue",
|
||||
b"/etc/motd",
|
||||
|
||||
# Other
|
||||
b"/etc/lsb-release" # set later in the build process
|
||||
)
|
||||
|
||||
|
||||
def provided_sonames():
|
||||
for cpv in VARDB.cpv_all():
|
||||
raw = VARDB.aux_get(cpv, ["PROVIDES"])[0]
|
||||
@ -94,11 +110,13 @@ def provided_sonames():
|
||||
for atom in VARDB.settings.soname_provided:
|
||||
yield atom
|
||||
|
||||
|
||||
def ignore_sonames(cpv):
|
||||
for key in dep.match_to_list(cpv, IGNORE_MISSING.iterkeys()):
|
||||
for atom in IGNORE_MISSING[key]:
|
||||
yield atom
|
||||
|
||||
|
||||
def missing_sonames():
|
||||
provided = frozenset(provided_sonames())
|
||||
for cpv in VARDB.cpv_all():
|
||||
@ -109,6 +127,7 @@ def missing_sonames():
|
||||
if missing:
|
||||
yield (cpv, missing)
|
||||
|
||||
|
||||
def usr_conflicts():
|
||||
for cpv in VARDB.cpv_all():
|
||||
raw = VARDB.aux_get(cpv, ["CONTENTS"])[0]
|
||||
@ -141,6 +160,7 @@ def usr_conflicts():
|
||||
if conflicts:
|
||||
yield (cpv, conflicts)
|
||||
|
||||
|
||||
def check_libs():
|
||||
ok = True
|
||||
for cpv, sonames in missing_sonames():
|
||||
@ -150,6 +170,7 @@ def check_libs():
|
||||
ok = False
|
||||
return ok
|
||||
|
||||
|
||||
def check_usr():
|
||||
ok = True
|
||||
for cpv, conflicts in usr_conflicts():
|
||||
@ -159,11 +180,13 @@ 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
|
||||
perms = stat.S_IROTH | stat.S_IXOTH
|
||||
mode = os.lstat(path).st_mode
|
||||
return stat.S_ISREG(mode) and mode&perms == perms
|
||||
return stat.S_ISREG(mode) and (mode & perms) == perms
|
||||
|
||||
|
||||
def check_shebang():
|
||||
ok = True
|
||||
@ -171,7 +194,7 @@ def check_shebang():
|
||||
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):
|
||||
if any(fnmatch.fnmatchcase(path, i) for i in IGNORE_SHEBANG):
|
||||
continue
|
||||
if not is_exe(path):
|
||||
continue
|
||||
@ -201,16 +224,66 @@ def check_shebang():
|
||||
ok = False
|
||||
return ok
|
||||
|
||||
|
||||
class chrooted():
|
||||
"""
|
||||
chrooted provides a context so that it can be used via with.
|
||||
For example:
|
||||
|
||||
with chrooted("/some/rootfs"):
|
||||
do_operations_in_rootfs()
|
||||
do_operations_not_in_rootfs()
|
||||
"""
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
def __enter__(self):
|
||||
self.restore_fd = os.open(b"/", os.O_RDONLY)
|
||||
self.working_dir = os.getcwd()
|
||||
|
||||
os.chroot(self.path)
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
os.fchdir(self.restore_fd)
|
||||
os.chroot(b".")
|
||||
os.chdir(self.working_dir)
|
||||
os.close(self.restore_fd)
|
||||
|
||||
|
||||
def check_symlink():
|
||||
if os.getuid() != 0:
|
||||
error("symlink check must be run as root (chroot)")
|
||||
return False
|
||||
|
||||
ok = True
|
||||
root = os.environ.get("ROOT", b"/")
|
||||
|
||||
with chrooted(root):
|
||||
for parent, dirs, files in os.walk(b"/"):
|
||||
for path in [os.path.join(parent, p) for p in files + dirs]:
|
||||
if any(fnmatch.fnmatchcase(path, i) for i in IGNORE_SYMLINK):
|
||||
continue
|
||||
|
||||
if os.path.islink(path) and not os.path.exists(path):
|
||||
ok = False
|
||||
error("broken link: %s", path)
|
||||
|
||||
return ok
|
||||
|
||||
|
||||
def error(fmt, *args):
|
||||
sys.stderr.write(output.red(fmt % args))
|
||||
sys.stderr.write("\n")
|
||||
|
||||
|
||||
def main():
|
||||
ok = True
|
||||
check_funcs = {
|
||||
"libs": check_libs,
|
||||
"usr": check_usr,
|
||||
"shebang": check_shebang,
|
||||
"symlink": check_symlink,
|
||||
}
|
||||
|
||||
if not sys.stderr.isatty():
|
||||
|
||||
@ -56,6 +56,11 @@ test_image_content() {
|
||||
#returncode=1
|
||||
fi
|
||||
|
||||
if ! sudo ROOT="$root" "$check_root" symlink; then
|
||||
error "test_image_content: Failed symlink check"
|
||||
returncode=1
|
||||
fi
|
||||
|
||||
if ! ROOT="$root" glsa_image; then
|
||||
returncode=1
|
||||
fi
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user