This file is indexed.

/usr/sbin/aa-unconfined is in apparmor-utils 2.10.95-0ubuntu2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/python3
# ----------------------------------------------------------------------
#    Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of version 2 of the GNU General Public
#    License as published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
# ----------------------------------------------------------------------
import argparse
import os
import re
import sys

import apparmor.aa as aa
import apparmor.ui as ui
import apparmor.common

# setup exception handling
from apparmor.fail import enable_aa_exception_handler
enable_aa_exception_handler()

# setup module translations
from apparmor.translations import init_translation
_ = 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"))
args = parser.parse_args()

paranoid = args.paranoid

aa_mountpoint = aa.check_for_apparmor()
if not aa_mountpoint:
    raise aa.AppArmorException(_("It seems AppArmor was not started. Please enable AppArmor and try again."))

pids = []
if paranoid:
    pids = list(filter(lambda x: re.search(r"^\d+$", x), aa.get_subdirectories("/proc")))
else:
    regex_tcp_udp = re.compile(r"^(tcp|udp)\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\s+)\s+(\d+)\/(\S+)")
    import subprocess
    if sys.version_info < (3, 0):
        output = subprocess.check_output("LANG=C netstat -nlp", shell=True).split("\n")
    else:
        #Python3 needs to translate a stream of bytes to string with specified encoding
        output = str(subprocess.check_output("LANG=C netstat -nlp", shell=True), encoding='utf8').split("\n")

    for line in output:
        match = regex_tcp_udp.search(line)
        if match:
            pids.append(match.groups()[4])
# We can safely remove duplicate pid's?
pids = list(map(int, set(pids)))

for pid in sorted(pids):
    try:
        prog = os.readlink("/proc/%s/exe"%pid)
    except OSError:
        continue
    attr = None
    if os.path.exists("/proc/%s/attr/current"%pid):
        with aa.open_file_read("/proc/%s/attr/current"%pid) as current:
            for line in current:
                line = line.strip()
                if line.endswith(' (complain)', 1) or line.endswith(' (enforce)', 1): # enforce at least one char as profile name
                    attr = line

    cmdline = apparmor.common.cmd(["cat", "/proc/%s/cmdline"%pid])[1]
    pname = cmdline.split("\0")[0]
    if '/' in pname and pname != prog:
        pname = "(%s)"% pname
    else:
        pname = ""
    regex_interpreter = re.compile(r"^(/usr)?/bin/(python|perl|bash|dash|sh)$")
    if not attr:
        if regex_interpreter.search(prog):
            cmdline = re.sub(r"\x00", " ", cmdline)
            cmdline = re.sub(r"\s+$", "", cmdline).strip()

            ui.UI_Info(_("%(pid)s %(program)s (%(commandline)s) not confined") % { 'pid': pid, 'program': prog, 'commandline': cmdline })
        else:
            if pname and pname[-1] == ')':
                pname = ' ' + pname
            ui.UI_Info(_("%(pid)s %(program)s%(pname)s not confined") % { 'pid': pid, 'program': prog, 'pname': pname })
    else:
        if regex_interpreter.search(prog):
            cmdline = re.sub(r"\0", " ", cmdline)
            cmdline = re.sub(r"\s+$", "", cmdline).strip()
            ui.UI_Info(_("%(pid)s %(program)s (%(commandline)s) confined by '%(attribute)s'") % { 'pid': pid, 'program': prog, 'commandline': cmdline, 'attribute': attr })
        else:
            if pname and pname[-1] == ')':
                pname = ' ' + pname
            ui.UI_Info(_("%(pid)s %(program)s%(pname)s confined by '%(attribute)s'") % { 'pid': pid, 'program': prog, 'pname': pname, 'attribute': attr })