diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2023-03-17 23:43:03 +0100 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2023-03-17 23:43:03 +0100 |
commit | 104e49ea4563e7d7ae9a1ffdba808e98bfec3615 (patch) | |
tree | aacaf809100b096948287bce92cd5ce8e681c831 /src/bad-attrs | |
parent | open-ports: use -Pn (diff) | |
download | audit-scripts-104e49ea4563e7d7ae9a1ffdba808e98bfec3615.tar.gz audit-scripts-104e49ea4563e7d7ae9a1ffdba808e98bfec3615.zip |
Diffstat (limited to 'src/bad-attrs')
-rwxr-xr-x | src/bad-attrs | 135 |
1 files changed, 0 insertions, 135 deletions
diff --git a/src/bad-attrs b/src/bad-attrs deleted file mode 100755 index 4683540..0000000 --- a/src/bad-attrs +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2023 Egor Tensin <Egor.Tensin@gmail.com> -# This file is part of the "audit-scripts" project. -# For details, see https://github.com/egor-tensin/audit-scripts. -# Distributed under the MIT License. - -import argparse -import array -from contextlib import contextmanager -import errno -import fcntl -import logging -import os -import stat -import sys - - -@contextmanager -def setup_logging(): - logging.basicConfig( - format='%(asctime)s | %(levelname)s | %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - level=logging.DEBUG) - try: - yield - except Exception as e: - logging.exception(e) - raise - - -def scandir(dir_path): - try: - entry_it = os.scandir(dir_path) - except (PermissionError, FileNotFoundError) as e: - logging.warning('%s', e) - return - with entry_it: - yield from entry_it - - -def traverse_tree(root): - queue = [root] - while queue: - for entry in scandir(queue.pop(0)): - if entry.is_dir(follow_symlinks=False): - if os.path.ismount(entry.path): - continue - queue.append(entry.path) - yield entry - - -def skip_leaf(entry): - if entry.is_dir(follow_symlinks=False): - return False - if entry.is_file(follow_symlinks=False): - return False - return True - - -@contextmanager -def low_level_open(path, flags): - fd = os.open(path, flags) - try: - yield fd - finally: - os.close(fd) - - -FS_IOC_GETFLAGS = 0x80086601 - -FS_IMMUTABLE_FL = 0x00000010 -FS_APPEND_FL = 0x00000020 - -BAD_FLAGS = [FS_IMMUTABLE_FL, FS_APPEND_FL] - - -def flags_contain_bad_flags(flags): - return any([flags & bad_flag for bad_flag in BAD_FLAGS]) - - -def fd_get_flags(fd): - a = array.array('L', [0]) - fcntl.ioctl(fd, FS_IOC_GETFLAGS, a, True) - return a[0] - - -def path_get_flags(path): - with low_level_open(path, os.O_RDONLY) as fd: - return fd_get_flags(fd) - - -def path_has_bad_flags(path): - try: - flags = path_get_flags(path) - except OSError as e: - if e.errno == errno.ENOTTY or e.errno == errno.EPERM: - # Either one of: - # Inappropriate ioctl for device - # Permission denied - # It's relied upon that fcntl throws OSError instead of - # PermissionError. - logging.warning('%s: %s', path, e) - return False - raise - return flags_contain_bad_flags(flags) - - -def do_dir(root): - logging.info('Directory: %s', root) - for entry in traverse_tree(root): - if skip_leaf(entry): - continue - #logging.debug('Path: %s', entry.path) - if path_has_bad_flags(entry.path): - logging.warning('Bad flags: %s', entry.path) - - -def parse_args(argv=None): - if argv is None: - argv = sys.argv[1:] - parser = argparse.ArgumentParser() - parser.add_argument('dir', metavar='DIR', - help='set root directory') - return parser.parse_args() - - -def main(argv=None): - with setup_logging(): - args = parse_args() - do_dir(args.dir) - - -if __name__ == '__main__': - main() |