mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
- added new aa-status tool rewritten in Python
- moved old Perl aa-status tool to the deprecated directory
This commit is contained in:
parent
12876afa07
commit
b9bfc10d0f
218
deprecated/utils/aa-status
Normal file
218
deprecated/utils/aa-status
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Copyright (C) 2005-2006 Novell/SUSE
|
||||||
|
#
|
||||||
|
# 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 published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Getopt::Long;
|
||||||
|
use Cwd 'abs_path';
|
||||||
|
|
||||||
|
my $confdir = "/etc/apparmor";
|
||||||
|
my $sd_mountpoint;
|
||||||
|
my $check_enabled = 0;
|
||||||
|
my $count_enforced = 0;
|
||||||
|
my $count_profiled = 0;
|
||||||
|
my $count_complain = 0;
|
||||||
|
my $verbose = 0;
|
||||||
|
my $help;
|
||||||
|
|
||||||
|
GetOptions(
|
||||||
|
'complaining' => \$count_complain,
|
||||||
|
'enabled' => \$check_enabled,
|
||||||
|
'enforced' => \$count_enforced,
|
||||||
|
'profiled' => \$count_profiled,
|
||||||
|
'verbose|v' => \$verbose,
|
||||||
|
'help|h' => \$help,
|
||||||
|
) or usage();
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
print "Usage: $0 [OPTIONS]\n";
|
||||||
|
print "Displays various information about the currently loaded AppArmor policy.\n";
|
||||||
|
print "OPTIONS (one only):\n";
|
||||||
|
print " --enabled returns error code if subdomain not enabled\n";
|
||||||
|
print " --profiled prints the number of loaded policies\n";
|
||||||
|
print " --enforced prints the number of loaded enforcing policies\n";
|
||||||
|
print " --complaining prints the number of loaded non-enforcing policies\n";
|
||||||
|
print " --verbose (default) displays multiple data points about loaded policy set\n";
|
||||||
|
print " --help this message\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$verbose = 1 if ($count_complain + $check_enabled + $count_enforced + $count_profiled == 0);
|
||||||
|
usage() if $help or ($count_complain + $check_enabled + $count_enforced + $count_profiled + $verbose > 1);
|
||||||
|
|
||||||
|
sub is_subdomain_loaded() {
|
||||||
|
return 1 if (-d "/sys/module/apparmor");
|
||||||
|
if(open(MODULES, "/proc/modules")) {
|
||||||
|
while(<MODULES>) {
|
||||||
|
return 1 if m/^(subdomain|apparmor)\s+/;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub find_subdomainfs() {
|
||||||
|
|
||||||
|
my $sd_mountpoint;
|
||||||
|
if(open(MOUNTS, "/proc/mounts")) {
|
||||||
|
while(<MOUNTS>) {
|
||||||
|
$sd_mountpoint = "$1/apparmor" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/apparmor";
|
||||||
|
$sd_mountpoint = "$1/subdomain" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/subdomain";
|
||||||
|
$sd_mountpoint = $1 if m/^\S+\s+(\S+)\s+subdomainfs\s/ && -e "$1";
|
||||||
|
}
|
||||||
|
close(MOUNTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sd_mountpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_profiles {
|
||||||
|
my $mountpoint = shift;
|
||||||
|
my %profiles = ();
|
||||||
|
|
||||||
|
if (open(PROFILES, "$mountpoint/profiles")) {
|
||||||
|
while(<PROFILES>) {
|
||||||
|
$profiles{$1} = $2 if m/^([^\(]+)\s+\((\w+)\)$/;
|
||||||
|
}
|
||||||
|
close(PROFILES);
|
||||||
|
}
|
||||||
|
return (%profiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_processes {
|
||||||
|
my %profiles = @_;
|
||||||
|
my %processes = ();
|
||||||
|
if (opendir(PROC, "/proc")) {
|
||||||
|
my $file;
|
||||||
|
while (defined($file = readdir(PROC))) {
|
||||||
|
if ($file =~ m/^\d+/) {
|
||||||
|
if (open(CURRENT, "/proc/$file/attr/current")) {
|
||||||
|
while (<CURRENT>) {
|
||||||
|
if (m/^([^\(]+)\s+\((\w+)\)$/) {
|
||||||
|
$processes{$file}{'profile'} = $1;
|
||||||
|
$processes{$file}{'mode'} = $2;
|
||||||
|
} elsif (grep(abs_path("/proc/$file/exe") eq $_ , keys(%profiles))) {
|
||||||
|
# keep only unconfined processes that have a profile defined
|
||||||
|
$processes{$file}{'profile'} = abs_path("/proc/$file/exe");
|
||||||
|
$processes{$file}{'mode'} = 'unconfined';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(CURRENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(PROC);
|
||||||
|
}
|
||||||
|
return (%processes);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $is_loaded = is_subdomain_loaded();
|
||||||
|
|
||||||
|
if (!$is_loaded) {
|
||||||
|
print STDERR "apparmor module is not loaded.\n" if $verbose;
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print "apparmor module is loaded.\n" if $verbose;
|
||||||
|
|
||||||
|
$sd_mountpoint = find_subdomainfs();
|
||||||
|
if (!$sd_mountpoint) {
|
||||||
|
print STDERR "apparmor filesystem is not mounted.\n" if $verbose;
|
||||||
|
exit 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! -r "$sd_mountpoint/profiles") {
|
||||||
|
print STDERR "You do not have enough privilege to read the profile set.\n" if $verbose;
|
||||||
|
exit 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#print "subdomainfs is at $sd_mountpoint.\n" if $verbose;
|
||||||
|
|
||||||
|
# processes is a hash table :
|
||||||
|
# * keys : processes pid
|
||||||
|
# * values : hash containing information about the running process:
|
||||||
|
# * 'profile' : name of the profile applied to the running process
|
||||||
|
# * 'mode' : mode of the profile applied to the running process
|
||||||
|
my %processes = ();
|
||||||
|
my %enforced_processes = ();
|
||||||
|
my %complain_processes = ();
|
||||||
|
my %unconfined_processes = ();
|
||||||
|
|
||||||
|
# profiles is a hash table :
|
||||||
|
# * keys : profile name
|
||||||
|
# * value : profile mode
|
||||||
|
my %profiles;
|
||||||
|
my @enforced_profiles = ();
|
||||||
|
my @complain_profiles = ();
|
||||||
|
|
||||||
|
%profiles = get_profiles($sd_mountpoint);
|
||||||
|
@enforced_profiles = grep { $profiles{$_} eq 'enforce' } keys %profiles;
|
||||||
|
@complain_profiles = grep { $profiles{$_} eq 'complain' } keys %profiles;
|
||||||
|
|
||||||
|
# we consider the case where no profiles are loaded to be "disabled" as well
|
||||||
|
my $rc = (keys(%profiles) == 0) ? 2 : 0;
|
||||||
|
|
||||||
|
if ($check_enabled) {
|
||||||
|
exit $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count_profiled) {
|
||||||
|
print scalar(keys(%profiles)). "\n";
|
||||||
|
exit $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count_enforced) {
|
||||||
|
print $#enforced_profiles + 1 . "\n";
|
||||||
|
exit $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count_complain) {
|
||||||
|
print $#complain_profiles + 1 . "\n";
|
||||||
|
exit $rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($verbose) {
|
||||||
|
print keys(%profiles) . " profiles are loaded.\n";
|
||||||
|
print $#enforced_profiles + 1 . " profiles are in enforce mode.\n";
|
||||||
|
for (sort(@enforced_profiles)) {
|
||||||
|
print " " . $_ . "\n";
|
||||||
|
}
|
||||||
|
print $#complain_profiles + 1 . " profiles are in complain mode.\n";
|
||||||
|
for (sort(@complain_profiles)) {
|
||||||
|
print " " . $_ . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%processes = get_processes(%profiles);
|
||||||
|
if ($verbose) {
|
||||||
|
for (keys(%processes)) {
|
||||||
|
$enforced_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'enforce';
|
||||||
|
$complain_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'complain';
|
||||||
|
# some early code uses unconfined instead of unconfined.
|
||||||
|
$unconfined_processes{$_} = $processes{$_} if $processes{$_}{'mode'} =~ /uncon(fi|strai)ned/;
|
||||||
|
}
|
||||||
|
print keys(%processes) . " processes have profiles defined.\n";
|
||||||
|
print keys(%enforced_processes) . " processes are in enforce mode :\n";
|
||||||
|
for (sort { $enforced_processes{$a}{'profile'} cmp $enforced_processes{$b}{'profile'} } keys(%enforced_processes)) {
|
||||||
|
print " " . $enforced_processes{$_}{'profile'} . " ($_) \n";
|
||||||
|
}
|
||||||
|
print keys(%complain_processes) . " processes are in complain mode.\n";
|
||||||
|
for (sort { $complain_processes{$a}{'profile'} cmp $complain_processes{$b}{'profile'} } keys(%complain_processes)) {
|
||||||
|
print " " . $complain_processes{$_}{'profile'} . " ($_) \n";
|
||||||
|
}
|
||||||
|
print keys(%unconfined_processes) . " processes are unconfined but have a profile defined.\n";
|
||||||
|
for (sort { $unconfined_processes{$a}{'profile'} cmp $unconfined_processes{$b}{'profile'} } keys(%unconfined_processes)) {
|
||||||
|
print " " . $unconfined_processes{$_}{'profile'} . " ($_) \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit $rc;
|
@ -28,8 +28,8 @@ endif
|
|||||||
|
|
||||||
MODDIR = Immunix
|
MODDIR = Immunix
|
||||||
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
|
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
|
||||||
aa-unconfined aa-status aa-notify aa-disable
|
aa-unconfined aa-notify aa-disable
|
||||||
TOOLS = ${PERLTOOLS} aa-decode
|
TOOLS = ${PERLTOOLS} aa-decode aa-status
|
||||||
MODULES = ${MODDIR}/AppArmor.pm ${MODDIR}/Repository.pm \
|
MODULES = ${MODDIR}/AppArmor.pm ${MODDIR}/Repository.pm \
|
||||||
${MODDIR}/Config.pm ${MODDIR}/Severity.pm
|
${MODDIR}/Config.pm ${MODDIR}/Severity.pm
|
||||||
|
|
||||||
|
384
utils/aa-status
Normal file → Executable file
384
utils/aa-status
Normal file → Executable file
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/python
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Copyright (C) 2005-2006 Novell/SUSE
|
# Copyright (C) 2005-2006 Novell/SUSE
|
||||||
|
# Copyright (C) 2011 Canonical Ltd.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
@ -9,210 +10,191 @@
|
|||||||
#
|
#
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
import re, os, sys
|
||||||
|
|
||||||
use strict;
|
def cmd_enabled():
|
||||||
use Getopt::Long;
|
'''Returns error code if AppArmor is not enabled'''
|
||||||
use Cwd 'abs_path';
|
if get_profiles() == {}:
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
my $confdir = "/etc/apparmor";
|
def cmd_profiled():
|
||||||
my $sd_mountpoint;
|
'''Prints the number of loaded profiles'''
|
||||||
my $check_enabled = 0;
|
profiles = get_profiles()
|
||||||
my $count_enforced = 0;
|
sys.stdout.write("%d\n" % len(profiles))
|
||||||
my $count_profiled = 0;
|
if profiles == {}:
|
||||||
my $count_complain = 0;
|
sys.exit(2)
|
||||||
my $verbose = 0;
|
|
||||||
my $help;
|
|
||||||
|
|
||||||
GetOptions(
|
def cmd_enforced():
|
||||||
'complaining' => \$count_complain,
|
'''Prints the number of loaded enforcing profiles'''
|
||||||
'enabled' => \$check_enabled,
|
profiles = get_profiles()
|
||||||
'enforced' => \$count_enforced,
|
sys.stdout.write("%d\n" % len(filter_profiles(profiles, 'enforce')))
|
||||||
'profiled' => \$count_profiled,
|
if profiles == {}:
|
||||||
'verbose|v' => \$verbose,
|
sys.exit(2)
|
||||||
'help|h' => \$help,
|
|
||||||
) or usage();
|
|
||||||
|
|
||||||
sub usage {
|
def cmd_complaining():
|
||||||
print "Usage: $0 [OPTIONS]\n";
|
'''Prints the number of loaded non-enforcing profiles'''
|
||||||
print "Displays various information about the currently loaded AppArmor policy.\n";
|
profiles = get_profiles()
|
||||||
print "OPTIONS (one only):\n";
|
sys.stdout.write("%d\n" % len(filter_profiles(profiles, 'complain')))
|
||||||
print " --enabled returns error code if subdomain not enabled\n";
|
if profiles == {}:
|
||||||
print " --profiled prints the number of loaded policies\n";
|
sys.exit(2)
|
||||||
print " --enforced prints the number of loaded enforcing policies\n";
|
|
||||||
print " --complaining prints the number of loaded non-enforcing policies\n";
|
def cmd_verbose():
|
||||||
print " --verbose (default) displays multiple data points about loaded policy set\n";
|
'''Displays multiple data points about loaded profile set'''
|
||||||
print " --help this message\n";
|
global verbose
|
||||||
exit;
|
verbose = True
|
||||||
|
profiles = get_profiles()
|
||||||
|
processes = get_processes(profiles)
|
||||||
|
|
||||||
|
stdmsg("%d profiles are loaded." % len(profiles))
|
||||||
|
for status in ('enforce', 'complain'):
|
||||||
|
filtered_profiles = filter_profiles(profiles, status)
|
||||||
|
stdmsg("%d profiles are in %s mode." % (len(filtered_profiles), status))
|
||||||
|
for item in filtered_profiles:
|
||||||
|
stdmsg(" %s" % item)
|
||||||
|
|
||||||
|
stdmsg("%d processes have profiles defined." % len(processes))
|
||||||
|
for status in ('enforce', 'complain', 'unconfined'):
|
||||||
|
filtered_processes = filter_processes(processes, status)
|
||||||
|
if status == 'unconfined':
|
||||||
|
stdmsg("%d processes are unconfined but have a profile defined." % len(filtered_processes))
|
||||||
|
else:
|
||||||
|
stdmsg("%d processes are in %s mode." % (len(filtered_processes), status))
|
||||||
|
# Sort by name, and then by pid
|
||||||
|
filtered_processes.sort(key=lambda x: int(x[0]))
|
||||||
|
filtered_processes.sort(key=lambda x: x[1])
|
||||||
|
for (pid, process) in filtered_processes:
|
||||||
|
stdmsg(" %s (%s) " % (process, pid))
|
||||||
|
|
||||||
|
if profiles == {}:
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
def get_profiles():
|
||||||
|
'''Fetch loaded profiles'''
|
||||||
|
|
||||||
|
profiles = {}
|
||||||
|
|
||||||
|
if os.path.exists("/sys/module/apparmor"):
|
||||||
|
stdmsg("apparmor module is loaded.")
|
||||||
|
else:
|
||||||
|
errormsg("apparmor module is not loaded.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
apparmorfs = find_apparmorfs()
|
||||||
|
if not apparmorfs:
|
||||||
|
errormsg("apparmor filesystem is not mounted.")
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
apparmor_profiles = os.path.join(apparmorfs, "profiles")
|
||||||
|
if not os.access(apparmor_profiles, os.R_OK):
|
||||||
|
errormsg("You do not have enough privilege to read the profile set.")
|
||||||
|
sys.exit(4)
|
||||||
|
|
||||||
|
for p in open(apparmor_profiles).readlines():
|
||||||
|
match = re.search("^([^\(]+)\s+\((\w+)\)$", p)
|
||||||
|
profiles[match.group(1)] = match.group(2)
|
||||||
|
|
||||||
|
return profiles
|
||||||
|
|
||||||
|
def get_processes(profiles):
|
||||||
|
'''Fetch process list'''
|
||||||
|
processes = {}
|
||||||
|
contents = os.listdir("/proc")
|
||||||
|
for filename in contents:
|
||||||
|
if filename.isdigit():
|
||||||
|
try:
|
||||||
|
for p in open("/proc/%s/attr/current" % filename).readlines():
|
||||||
|
match = re.search("^([^\(]+)\s+\((\w+)\)$", p)
|
||||||
|
if match:
|
||||||
|
processes[filename] = { 'profile' : match.group(1), \
|
||||||
|
'mode' : match.group(2) }
|
||||||
|
elif os.path.realpath("/proc/%s/exe" % filename) in profiles:
|
||||||
|
# keep only unconfined processes that have a profile defined
|
||||||
|
processes[filename] = { 'profile' : os.path.realpath("/proc/%s/exe" % filename), \
|
||||||
|
'mode' : 'unconfined' }
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return processes
|
||||||
|
|
||||||
|
def filter_profiles(profiles, status):
|
||||||
|
'''Return a list of profiles that have a particular status'''
|
||||||
|
filtered = []
|
||||||
|
for key, value in list(profiles.items()):
|
||||||
|
if value == status:
|
||||||
|
filtered.append(key)
|
||||||
|
filtered.sort()
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
def filter_processes(processes, status):
|
||||||
|
'''Return a list of processes that have a particular status'''
|
||||||
|
filtered = []
|
||||||
|
for key, value in list(processes.items()):
|
||||||
|
if value['mode'] == status:
|
||||||
|
filtered.append([key, value['profile']])
|
||||||
|
return filtered
|
||||||
|
|
||||||
|
def find_apparmorfs():
|
||||||
|
'''Finds AppArmor mount point'''
|
||||||
|
for p in open("/proc/mounts").readlines():
|
||||||
|
if p.split()[2] == "securityfs" and \
|
||||||
|
os.path.exists(os.path.join(p.split()[1], "apparmor")):
|
||||||
|
return os.path.join(p.split()[1], "apparmor")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def errormsg(message):
|
||||||
|
'''Prints to stderr if verbose mode is on'''
|
||||||
|
global verbose
|
||||||
|
if verbose:
|
||||||
|
sys.stderr.write(message + "\n")
|
||||||
|
|
||||||
|
def stdmsg(message):
|
||||||
|
'''Prints to stdout if verbose mode is on'''
|
||||||
|
global verbose
|
||||||
|
if verbose:
|
||||||
|
sys.stdout.write(message + "\n")
|
||||||
|
|
||||||
|
def print_usage():
|
||||||
|
'''Print usage information'''
|
||||||
|
sys.stdout.write('''Usage: %s [OPTIONS]
|
||||||
|
Displays various information about the currently loaded AppArmor policy.
|
||||||
|
OPTIONS (one only):
|
||||||
|
--enabled returns error code if AppArmor not enabled
|
||||||
|
--profiled prints the number of loaded policies
|
||||||
|
--enforced prints the number of loaded enforcing policies
|
||||||
|
--complaining prints the number of loaded non-enforcing policies
|
||||||
|
--verbose (default) displays multiple data points about loaded policy set
|
||||||
|
--help this message
|
||||||
|
''' % sys.argv[0])
|
||||||
|
|
||||||
|
# Main
|
||||||
|
global verbose
|
||||||
|
verbose = False
|
||||||
|
|
||||||
|
if len(sys.argv) > 2:
|
||||||
|
sys.stderr.write("Error: Too many options.\n")
|
||||||
|
print_usage()
|
||||||
|
sys.exit(1)
|
||||||
|
elif len(sys.argv) == 2:
|
||||||
|
cmd = sys.argv.pop(1)
|
||||||
|
else:
|
||||||
|
cmd = '--verbose'
|
||||||
|
|
||||||
|
# Command dispatch:
|
||||||
|
commands = {
|
||||||
|
'--enabled' : cmd_enabled,
|
||||||
|
'--profiled' : cmd_profiled,
|
||||||
|
'--enforced' : cmd_enforced,
|
||||||
|
'--complaining' : cmd_complaining,
|
||||||
|
'--verbose' : cmd_verbose,
|
||||||
|
'-v' : cmd_verbose,
|
||||||
|
'--help' : print_usage,
|
||||||
|
'-h' : print_usage
|
||||||
}
|
}
|
||||||
|
|
||||||
$verbose = 1 if ($count_complain + $check_enabled + $count_enforced + $count_profiled == 0);
|
if cmd in commands:
|
||||||
usage() if $help or ($count_complain + $check_enabled + $count_enforced + $count_profiled + $verbose > 1);
|
commands[cmd]()
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
sys.stderr.write("Error: Invalid command.\n")
|
||||||
|
print_usage()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
sub is_subdomain_loaded() {
|
|
||||||
return 1 if (-d "/sys/module/apparmor");
|
|
||||||
if(open(MODULES, "/proc/modules")) {
|
|
||||||
while(<MODULES>) {
|
|
||||||
return 1 if m/^(subdomain|apparmor)\s+/;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub find_subdomainfs() {
|
|
||||||
|
|
||||||
my $sd_mountpoint;
|
|
||||||
if(open(MOUNTS, "/proc/mounts")) {
|
|
||||||
while(<MOUNTS>) {
|
|
||||||
$sd_mountpoint = "$1/apparmor" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/apparmor";
|
|
||||||
$sd_mountpoint = "$1/subdomain" if m/^\S+\s+(\S+)\s+securityfs\s/ && -e "$1/subdomain";
|
|
||||||
$sd_mountpoint = $1 if m/^\S+\s+(\S+)\s+subdomainfs\s/ && -e "$1";
|
|
||||||
}
|
|
||||||
close(MOUNTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $sd_mountpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_profiles {
|
|
||||||
my $mountpoint = shift;
|
|
||||||
my %profiles = ();
|
|
||||||
|
|
||||||
if (open(PROFILES, "$mountpoint/profiles")) {
|
|
||||||
while(<PROFILES>) {
|
|
||||||
$profiles{$1} = $2 if m/^([^\(]+)\s+\((\w+)\)$/;
|
|
||||||
}
|
|
||||||
close(PROFILES);
|
|
||||||
}
|
|
||||||
return (%profiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_processes {
|
|
||||||
my %profiles = @_;
|
|
||||||
my %processes = ();
|
|
||||||
if (opendir(PROC, "/proc")) {
|
|
||||||
my $file;
|
|
||||||
while (defined($file = readdir(PROC))) {
|
|
||||||
if ($file =~ m/^\d+/) {
|
|
||||||
if (open(CURRENT, "/proc/$file/attr/current")) {
|
|
||||||
while (<CURRENT>) {
|
|
||||||
if (m/^([^\(]+)\s+\((\w+)\)$/) {
|
|
||||||
$processes{$file}{'profile'} = $1;
|
|
||||||
$processes{$file}{'mode'} = $2;
|
|
||||||
} elsif (grep(abs_path("/proc/$file/exe") eq $_ , keys(%profiles))) {
|
|
||||||
# keep only unconfined processes that have a profile defined
|
|
||||||
$processes{$file}{'profile'} = abs_path("/proc/$file/exe");
|
|
||||||
$processes{$file}{'mode'} = 'unconfined';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(CURRENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(PROC);
|
|
||||||
}
|
|
||||||
return (%processes);
|
|
||||||
}
|
|
||||||
|
|
||||||
my $is_loaded = is_subdomain_loaded();
|
|
||||||
|
|
||||||
if (!$is_loaded) {
|
|
||||||
print STDERR "apparmor module is not loaded.\n" if $verbose;
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
print "apparmor module is loaded.\n" if $verbose;
|
|
||||||
|
|
||||||
$sd_mountpoint = find_subdomainfs();
|
|
||||||
if (!$sd_mountpoint) {
|
|
||||||
print STDERR "apparmor filesystem is not mounted.\n" if $verbose;
|
|
||||||
exit 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! -r "$sd_mountpoint/profiles") {
|
|
||||||
print STDERR "You do not have enough privilege to read the profile set.\n" if $verbose;
|
|
||||||
exit 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
#print "subdomainfs is at $sd_mountpoint.\n" if $verbose;
|
|
||||||
|
|
||||||
# processes is a hash table :
|
|
||||||
# * keys : processes pid
|
|
||||||
# * values : hash containing information about the running process:
|
|
||||||
# * 'profile' : name of the profile applied to the running process
|
|
||||||
# * 'mode' : mode of the profile applied to the running process
|
|
||||||
my %processes = ();
|
|
||||||
my %enforced_processes = ();
|
|
||||||
my %complain_processes = ();
|
|
||||||
my %unconfined_processes = ();
|
|
||||||
|
|
||||||
# profiles is a hash table :
|
|
||||||
# * keys : profile name
|
|
||||||
# * value : profile mode
|
|
||||||
my %profiles;
|
|
||||||
my @enforced_profiles = ();
|
|
||||||
my @complain_profiles = ();
|
|
||||||
|
|
||||||
%profiles = get_profiles($sd_mountpoint);
|
|
||||||
@enforced_profiles = grep { $profiles{$_} eq 'enforce' } keys %profiles;
|
|
||||||
@complain_profiles = grep { $profiles{$_} eq 'complain' } keys %profiles;
|
|
||||||
|
|
||||||
# we consider the case where no profiles are loaded to be "disabled" as well
|
|
||||||
my $rc = (keys(%profiles) == 0) ? 2 : 0;
|
|
||||||
|
|
||||||
if ($check_enabled) {
|
|
||||||
exit $rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count_profiled) {
|
|
||||||
print scalar(keys(%profiles)). "\n";
|
|
||||||
exit $rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count_enforced) {
|
|
||||||
print $#enforced_profiles + 1 . "\n";
|
|
||||||
exit $rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($count_complain) {
|
|
||||||
print $#complain_profiles + 1 . "\n";
|
|
||||||
exit $rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ($verbose) {
|
|
||||||
print keys(%profiles) . " profiles are loaded.\n";
|
|
||||||
print $#enforced_profiles + 1 . " profiles are in enforce mode.\n";
|
|
||||||
for (sort(@enforced_profiles)) {
|
|
||||||
print " " . $_ . "\n";
|
|
||||||
}
|
|
||||||
print $#complain_profiles + 1 . " profiles are in complain mode.\n";
|
|
||||||
for (sort(@complain_profiles)) {
|
|
||||||
print " " . $_ . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
%processes = get_processes(%profiles);
|
|
||||||
if ($verbose) {
|
|
||||||
for (keys(%processes)) {
|
|
||||||
$enforced_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'enforce';
|
|
||||||
$complain_processes{$_} = $processes{$_} if $processes{$_}{'mode'} eq 'complain';
|
|
||||||
# some early code uses unconfined instead of unconfined.
|
|
||||||
$unconfined_processes{$_} = $processes{$_} if $processes{$_}{'mode'} =~ /uncon(fi|strai)ned/;
|
|
||||||
}
|
|
||||||
print keys(%processes) . " processes have profiles defined.\n";
|
|
||||||
print keys(%enforced_processes) . " processes are in enforce mode :\n";
|
|
||||||
for (sort { $enforced_processes{$a}{'profile'} cmp $enforced_processes{$b}{'profile'} } keys(%enforced_processes)) {
|
|
||||||
print " " . $enforced_processes{$_}{'profile'} . " ($_) \n";
|
|
||||||
}
|
|
||||||
print keys(%complain_processes) . " processes are in complain mode.\n";
|
|
||||||
for (sort { $complain_processes{$a}{'profile'} cmp $complain_processes{$b}{'profile'} } keys(%complain_processes)) {
|
|
||||||
print " " . $complain_processes{$_}{'profile'} . " ($_) \n";
|
|
||||||
}
|
|
||||||
print keys(%unconfined_processes) . " processes are unconfined but have a profile defined.\n";
|
|
||||||
for (sort { $unconfined_processes{$a}{'profile'} cmp $unconfined_processes{$b}{'profile'} } keys(%unconfined_processes)) {
|
|
||||||
print " " . $unconfined_processes{$_}{'profile'} . " ($_) \n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit $rc;
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user