This patch allows a user to specify a specific location for ss or netstat for use in aa-unconfined, allowing a user to work around a tool that's buggy, uninstalled, or installed in an unexpected location. Note this option in the manpage.
[The downside to this patch is that if an environment uses something like a restrictive sudo policy around aa-unconfined, this would possibly give a user a way to subvert that. So I'm ambivalent about this patch.] Signed-off-by: Steve Beattie <[email protected]> --- utils/aa-unconfined | 24 +++++++++++++++--------- utils/aa-unconfined.pod | 8 +++++--- 2 files changed, 20 insertions(+), 12 deletions(-) Index: b/utils/aa-unconfined =================================================================== --- a/utils/aa-unconfined +++ b/utils/aa-unconfined @@ -34,8 +34,8 @@ _ = init_translation() parser = argparse.ArgumentParser(description=_("Lists unconfined processes having tcp or udp ports")) parser.add_argument("--paranoid", action="store_true", help=_("scan all processes from /proc")) bin_group = parser.add_mutually_exclusive_group() -bin_group.add_argument("--with-ss", action='store_true', help=_("use ss(8) to find listening processes (default)")) -bin_group.add_argument("--with-netstat", action='store_true', help=_("use netstat(8) to find listening processes")) +bin_group.add_argument("--with-ss", nargs='?', const='ss', metavar='SS_PATH', help=_("use ss(8) to find listening processes (default)")) +bin_group.add_argument("--with-netstat", nargs='?', const='netstat', metavar='NETSTAT_PATH', help=_("use netstat(8) to find listening processes")) args = parser.parse_args() paranoid = args.paranoid @@ -50,17 +50,20 @@ def get_all_pids(): return set(filter(lambda x: re.search(r"^\d+$", x), aa.get_subdirectories("/proc"))) -def get_pids_ss(): +def get_pids_ss(ss): '''Get a set of pids listening on network sockets via ss(8)''' regex_lines = re.compile(r"^(tcp|udp|raw|p_dgr)\s.+\s+users:(?P<users>\(\(.*\)\))$") regex_users_pids = re.compile(r'(\("[^"]+",(pid=)?(\d+),[^)]+\))') + if ss is None: + ss = 'ss' + pids = set() my_env = os.environ.copy() my_env['LANG'] = 'C' my_env['PATH'] = '/bin:/usr/bin:/sbin:/usr/sbin' for family in ['inet', 'inet6', 'link']: - cmd = ['ss', '-nlp', '--family', family] + cmd = [ss, '-nlp', '--family', family] if sys.version_info < (3, 0): output = subprocess.check_output(cmd, shell=False, env=my_env).split("\n") else: @@ -76,11 +79,14 @@ def get_pids_ss(): return pids -def get_pids_netstat(): +def get_pids_netstat(netstat): '''Get a set of pids listening on network sockets via netstat(8)''' regex_tcp_udp = re.compile(r"^(tcp|udp|raw)6?\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\d+|\s+)\s+(?P<pid>\d+)\/(\S+)") - cmd = ['netstat', '-nlp', '--protocol', 'inet,inet6'] + if netstat is None: + netstat = 'netstat' + + cmd = [netstat, '-nlp', '--protocol', 'inet,inet6'] my_env = os.environ.copy() my_env['LANG'] = 'C' my_env['PATH'] = '/bin:/usr/bin:/sbin:/usr/sbin' @@ -101,10 +107,10 @@ def get_pids_netstat(): pids = set() if paranoid: pids = get_all_pids() -elif args.with_ss or (not args.with_netstat and (os.path.exists('/bin/ss') or os.path.exists('/usr/bin/ss'))): - pids = get_pids_ss() +elif args.with_ss is not None or (args.with_netstat is None and (os.path.exists('/bin/ss') or os.path.exists('/usr/bin/ss'))): + pids = get_pids_ss(args.with_ss) else: - pids = get_pids_netstat() + pids = get_pids_netstat(args.with_netstat) for pid in sorted(map(int, pids)): try: Index: b/utils/aa-unconfined.pod =================================================================== --- a/utils/aa-unconfined.pod +++ b/utils/aa-unconfined.pod @@ -27,7 +27,7 @@ not have AppArmor profiles loaded =head1 SYNOPSIS -B<aa-unconfined [I<--paranoid>] [I<--with-ss> | I<--with-netstat>]> +B<aa-unconfined [I<--paranoid>] [I<--with-ss> [SS_PATH] | I<--with-netstat> [NETSTAT_PATH]]> =head1 OPTIONS @@ -41,13 +41,15 @@ that do not have AppArmor profiles loade =item B<--with-ss> Use the ss(8) command to find processes listening on network sockets -(the default). +(the default). An alternate ss binary can be specified using the +optional I<SS_PATH> argument. =item B<--with-netstat> Use the netstat(8) command to find processes listening on network sockets. This is also what aa-unconfined will fall back to when ss(8) -is not available. +is not available. An alternate netstat binary can be specified using +the optional I<NETSTAT_PATH> argument. =back -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
