Prevent ANSI terminal injection in aa-unconfined

/proc/$pid/cmdline can be changed by an application, therefore escape it
before printing.

The program name in /proc/$pid/exe can also contain any characters
(except \0 and shashes) and needs escaping.

Note: repr() wraps the string into single quotes, which we have to
remove to avoid changing the output format.

The test program from issue 364 now gets displayed as

    28443 /path/to/issue364 (/\x1b]0;X\x07) not confined

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/364
This commit is contained in:
Christian Boltz 2024-01-20 20:08:39 +01:00
parent 253eace573
commit 6cc3a3642d
Failed to generate hash of commit

View file

@ -112,6 +112,15 @@ def read_proc_current(filename):
return attr
def escape_special_chars(data):
"""escape special characters in program names so that they can't mess up the terminal"""
data = repr(data)
if len(data) > 1 and data.startswith("'") and data.endswith("'"):
return data[1:-1]
else:
return data
pids = set()
if paranoid:
pids = get_all_pids()
@ -123,6 +132,7 @@ else:
for pid in sorted(map(int, pids)):
try:
prog = os.readlink("/proc/%s/exe" % pid)
prog = escape_special_chars(prog)
except OSError:
continue
@ -139,6 +149,7 @@ for pid in sorted(map(int, pids)):
pname = cmdline.split("\0")[0]
if '/' in pname and pname != prog:
pname = "(%s)" % pname
pname = escape_special_chars(pname)
else:
pname = ""
regex_interpreter = re.compile(r"^(/usr)?/bin/(python|perl|bash|dash|sh)$")
@ -146,6 +157,7 @@ for pid in sorted(map(int, pids)):
if regex_interpreter.search(prog):
cmdline = re.sub(r"\x00", " ", cmdline)
cmdline = re.sub(r"\s+$", "", cmdline).strip()
cmdline = escape_special_chars(cmdline)
ui.UI_Info(_("%(pid)s %(program)s (%(commandline)s) not confined") % {'pid': pid, 'program': prog, 'commandline': cmdline})
else:
@ -156,6 +168,7 @@ for pid in sorted(map(int, pids)):
if regex_interpreter.search(prog):
cmdline = re.sub(r"\0", " ", cmdline)
cmdline = re.sub(r"\s+$", "", cmdline).strip()
cmdline = escape_special_chars(cmdline)
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] == ')':