mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00

Merge from 2.10 branch commit rev 3380 It was reported that converting the netstat command to examine processes bound to ipv6 addresses broke on OpenSUSE due to the version of nettools not supporting the short -4 -6 arguments. This patch fixes the invocation of netstat to use the "--protocol inet,inet6" arguments instead, which should return the same results as the short options. Signed-off-by: Steve Beattie <steve@nxnw.org> Acked-by: Christian Boltz <apparmor@cboltz.de>
95 lines
4 KiB
Python
Executable file
95 lines
4 KiB
Python
Executable file
#! /usr/bin/env python
|
|
# ----------------------------------------------------------------------
|
|
# 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 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|raw)6?\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\d+|\s+)\s+(\d+)\/(\S+)")
|
|
import subprocess
|
|
if sys.version_info < (3, 0):
|
|
output = subprocess.check_output("LANG=C netstat -nlp --protocol inet,inet6", 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 --protocol inet,inet6", 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 })
|