mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00
Fixes from review 52-53, merging cleanprof into apparmor/tools.py corrected enforce() and complain() to create/remove symlinks to force-complain/disable subdirs. Wrote some tests for globbing methods, segregated glob-path and glob-path-with-extension into methods in aa.py
This commit is contained in:
parent
781ff9c3d9
commit
27efe62a92
15 changed files with 256 additions and 286 deletions
|
@ -5,13 +5,68 @@ sys.path.append('../')
|
||||||
import apparmor.aa
|
import apparmor.aa
|
||||||
import apparmor.logparser
|
import apparmor.logparser
|
||||||
|
|
||||||
#from apparmor.aa import parse_event
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.MODE_TEST = {'x': apparmor.aamode.AA_MAY_EXEC,
|
||||||
|
'w': apparmor.aamode.AA_MAY_WRITE,
|
||||||
|
'r': apparmor.aamode.AA_MAY_READ,
|
||||||
|
'a': apparmor.aamode.AA_MAY_APPEND,
|
||||||
|
'l': apparmor.aamode.AA_MAY_LINK,
|
||||||
|
'k': apparmor.aamode.AA_MAY_LOCK,
|
||||||
|
'm': apparmor.aamode.AA_EXEC_MMAP,
|
||||||
|
'i': apparmor.aamode.AA_EXEC_INHERIT,
|
||||||
|
'u': apparmor.aamode.AA_EXEC_UNCONFINED | apparmor.aamode.AA_EXEC_UNSAFE,
|
||||||
|
'U': apparmor.aamode.AA_EXEC_UNCONFINED,
|
||||||
|
'p': apparmor.aamode.AA_EXEC_PROFILE | apparmor.aamode.AA_EXEC_UNSAFE,
|
||||||
|
'P': apparmor.aamode.AA_EXEC_PROFILE,
|
||||||
|
'c': apparmor.aamode.AA_EXEC_CHILD | apparmor.aamode.AA_EXEC_UNSAFE,
|
||||||
|
'C': apparmor.aamode.AA_EXEC_CHILD,
|
||||||
|
}
|
||||||
|
|
||||||
def test_loadinclude(self):
|
def test_loadinclude(self):
|
||||||
apparmor.aa.loadincludes()
|
apparmor.aa.loadincludes()
|
||||||
|
|
||||||
|
def test_path_globs(self):
|
||||||
|
globs = {
|
||||||
|
'/foo/': '/*/',
|
||||||
|
'/foo': '/*',
|
||||||
|
'/b*': '/*',
|
||||||
|
'/*b': '/*',
|
||||||
|
'/*': '/*',
|
||||||
|
'/*/': '/*/',
|
||||||
|
'/*.foo/': '/*/',
|
||||||
|
'/**.foo/': '/**/',
|
||||||
|
'/foo/*/': '/**/',
|
||||||
|
'/usr/foo/*': '/usr/**',
|
||||||
|
'/usr/foo/**': '/usr/**',
|
||||||
|
'/usr/foo/bar**': '/usr/foo/**',
|
||||||
|
'/usr/foo/**barr': '/usr/foo/**',
|
||||||
|
'/usr/foo/**/bar': '/usr/foo/**/*',
|
||||||
|
'/usr/foo/**/*': '/usr/foo/**',
|
||||||
|
'/usr/foo/*/bar': '/usr/foo/*/*',
|
||||||
|
'/usr/foo/*/*': '/usr/foo/**',
|
||||||
|
'/usr/foo/*/**': '/usr/foo/**'
|
||||||
|
}
|
||||||
|
for path in globs.keys():
|
||||||
|
self.assertEqual(apparmor.aa.glob_path(path), globs[path], 'Unexpected glob generated for path: %s'%path)
|
||||||
|
|
||||||
|
def test_path_withext_globs(self):
|
||||||
|
globs = {
|
||||||
|
'/foo/bar': '/foo/bar',
|
||||||
|
'/foo/**/bar': '/foo/**/bar',
|
||||||
|
'/foo.bar': '/*.bar',
|
||||||
|
'/*.foo': '/*.foo' ,
|
||||||
|
'/usr/*.bar': '/**.bar',
|
||||||
|
'/usr/**.bar': '/**.bar',
|
||||||
|
'/usr/foo**.bar': '/usr/**.bar',
|
||||||
|
'/usr/foo*.bar': '/usr/*.bar',
|
||||||
|
'/usr/**foo.bar': '/usr/**.bar',
|
||||||
|
'/usr/*foo.bar': '/usr/*.bar',
|
||||||
|
'/usr/foo.b*': '/usr/*.b*'
|
||||||
|
}
|
||||||
|
for path in globs.keys():
|
||||||
|
self.assertEqual(apparmor.aa.glob_path_withext(path), globs[path], 'Unexpected glob generated for path: %s'%path)
|
||||||
|
|
||||||
def test_parse_event(self):
|
def test_parse_event(self):
|
||||||
parser = apparmor.logparser.ReadLog('', '', '', '', '')
|
parser = apparmor.logparser.ReadLog('', '', '', '', '')
|
||||||
|
@ -38,27 +93,9 @@ class Test(unittest.TestCase):
|
||||||
|
|
||||||
def test_modes_to_string(self):
|
def test_modes_to_string(self):
|
||||||
|
|
||||||
MODE_TEST = {'x': apparmor.aamode.AA_MAY_EXEC,
|
|
||||||
'w': apparmor.aamode.AA_MAY_WRITE,
|
for string in self.MODE_TEST.keys():
|
||||||
'r': apparmor.aamode.AA_MAY_READ,
|
mode = self.MODE_TEST[string]
|
||||||
'a': apparmor.aamode.AA_MAY_APPEND,
|
|
||||||
'l': apparmor.aamode.AA_MAY_LINK,
|
|
||||||
'k': apparmor.aamode.AA_MAY_LOCK,
|
|
||||||
'm': apparmor.aamode.AA_EXEC_MMAP,
|
|
||||||
'i': apparmor.aamode.AA_EXEC_INHERIT,
|
|
||||||
'u': apparmor.aamode.AA_EXEC_UNCONFINED | apparmor.aamode.AA_EXEC_UNSAFE, # Unconfined + Unsafe
|
|
||||||
'U': apparmor.aamode.AA_EXEC_UNCONFINED,
|
|
||||||
'p': apparmor.aamode.AA_EXEC_PROFILE | apparmor.aamode.AA_EXEC_UNSAFE, # Profile + unsafe
|
|
||||||
'P': apparmor.aamode.AA_EXEC_PROFILE,
|
|
||||||
'c': apparmor.aamode.AA_EXEC_CHILD | apparmor.aamode.AA_EXEC_UNSAFE, # Child + Unsafe
|
|
||||||
'C': apparmor.aamode.AA_EXEC_CHILD,
|
|
||||||
#'n': apparmor.aamode.AA_EXEC_NT | apparmor.aamode.AA_EXEC_UNSAFE,
|
|
||||||
#'N': apparmor.aamode.AA_EXEC_NT
|
|
||||||
}
|
|
||||||
#for i in MODE_TEST.keys():
|
|
||||||
# print(i, MODE_TEST[i])
|
|
||||||
while MODE_TEST:
|
|
||||||
string,mode = MODE_TEST.popitem()
|
|
||||||
self.assertEqual(apparmor.aamode.mode_to_str(mode), string, 'mode is %s and string is %s'%(mode, string))
|
self.assertEqual(apparmor.aamode.mode_to_str(mode), string, 'mode is %s and string is %s'%(mode, string))
|
||||||
|
|
||||||
def test_string_to_modes(self):
|
def test_string_to_modes(self):
|
||||||
|
@ -78,8 +115,6 @@ class Test(unittest.TestCase):
|
||||||
'P': apparmor.aamode.AA_EXEC_PROFILE,
|
'P': apparmor.aamode.AA_EXEC_PROFILE,
|
||||||
'c': apparmor.aamode.AA_EXEC_CHILD | apparmor.aamode.AA_EXEC_UNSAFE, # Child + Unsafe
|
'c': apparmor.aamode.AA_EXEC_CHILD | apparmor.aamode.AA_EXEC_UNSAFE, # Child + Unsafe
|
||||||
'C': apparmor.aamode.AA_EXEC_CHILD,
|
'C': apparmor.aamode.AA_EXEC_CHILD,
|
||||||
#'n': apparmor.aamode.AA_EXEC_NT | apparmor.aamode.AA_EXEC_UNSAFE,
|
|
||||||
#'N': apparmor.aamode.AA_EXEC_NT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#while MODE_TEST:
|
#while MODE_TEST:
|
||||||
|
|
28
Testing/minitools_test.py
Normal file
28
Testing/minitools_test.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import unittest
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
#copy the local profiles to the test directory
|
||||||
|
shutil.copytree('/etc/apparmor.d/', './profiles/')
|
||||||
|
|
||||||
|
def test_audit(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_complain(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_enforce(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_disable(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_autodep(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
#import sys;sys.argv = ['', 'Test.testName']
|
||||||
|
unittest.main()
|
|
@ -1,35 +0,0 @@
|
||||||
# ------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Copyright (C) 2002-2009 Novell/SUSE
|
|
||||||
# Copyright (C) 2010 Canonical Ltd.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include <tunables/global>
|
|
||||||
|
|
||||||
/sbin/klogd {
|
|
||||||
#include <abstractions/base>
|
|
||||||
|
|
||||||
capability sys_admin, # for backward compatibility with kernel <= 2.6.37
|
|
||||||
capability syslog,
|
|
||||||
|
|
||||||
network inet stream,
|
|
||||||
|
|
||||||
/boot/System.map* r,
|
|
||||||
@{PROC}/kmsg r,
|
|
||||||
@{PROC}/kallsyms r,
|
|
||||||
/dev/tty rw,
|
|
||||||
|
|
||||||
/sbin/klogd rmix,
|
|
||||||
/var/log/boot.msg rwl,
|
|
||||||
/{,var/}run/klogd.pid krwl,
|
|
||||||
/{,var/}run/klogd/klogd.pid krwl,
|
|
||||||
/{,var/}run/klogd/kmsg r,
|
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
|
||||||
#include <local/sbin.klogd>
|
|
||||||
}
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
@ -8,6 +9,10 @@ from apparmor.common import AppArmorException
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
class Test(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
#copy the local profiles to the test directory
|
||||||
|
shutil.copytree('/etc/apparmor.d/', './profiles/')
|
||||||
|
|
||||||
def testRank_Test(self):
|
def testRank_Test(self):
|
||||||
#z = severity.Severity()
|
#z = severity.Severity()
|
||||||
|
|
||||||
|
@ -34,14 +39,14 @@ class Test(unittest.TestCase):
|
||||||
self.assertEqual(s.rank('/etc/**', 'r') , 10, 'Invalid Rank')
|
self.assertEqual(s.rank('/etc/**', 'r') , 10, 'Invalid Rank')
|
||||||
|
|
||||||
# Load all variables for /sbin/klogd and test them
|
# Load all variables for /sbin/klogd and test them
|
||||||
s.load_variables('sbin.klogd')
|
s.load_variables('profiles/sbin.klogd')
|
||||||
self.assertEqual(s.rank('@{PROC}/sys/vm/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
self.assertEqual(s.rank('@{PROC}/sys/vm/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
||||||
self.assertEqual(s.rank('@{HOME}/sys/@{PROC}/overcommit_memory', 'r'), 10, 'Invalid Rank')
|
self.assertEqual(s.rank('@{HOME}/sys/@{PROC}/overcommit_memory', 'r'), 10, 'Invalid Rank')
|
||||||
self.assertEqual(s.rank('/overco@{multiarch}mmit_memory', 'r'), 10, 'Invalid Rank')
|
self.assertEqual(s.rank('/overco@{multiarch}mmit_memory', 'r'), 10, 'Invalid Rank')
|
||||||
|
|
||||||
s.unload_variables()
|
s.unload_variables()
|
||||||
|
|
||||||
s.load_variables('usr.sbin.dnsmasq')
|
s.load_variables('profiles/usr.sbin.dnsmasq')
|
||||||
self.assertEqual(s.rank('@{PROC}/sys/@{TFTP_DIR}/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
self.assertEqual(s.rank('@{PROC}/sys/@{TFTP_DIR}/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
||||||
self.assertEqual(s.rank('@{PROC}/sys/vm/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
self.assertEqual(s.rank('@{PROC}/sys/vm/overcommit_memory', 'r'), 6, 'Invalid Rank')
|
||||||
self.assertEqual(s.rank('@{HOME}/sys/@{PROC}/overcommit_memory', 'r'), 10, 'Invalid Rank')
|
self.assertEqual(s.rank('@{HOME}/sys/@{PROC}/overcommit_memory', 'r'), 10, 'Invalid Rank')
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
# ------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Copyright (C) 2009 John Dong <jdong@ubuntu.com>
|
|
||||||
# Copyright (C) 2010 Canonical Ltd.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
@{TFTP_DIR}=/var/tftp /srv/tftpboot #comment
|
|
||||||
|
|
||||||
#include <tunables/global> # comment
|
|
||||||
/usr/sbin/dnsmasq {
|
|
||||||
#include <abstractions/base>
|
|
||||||
#include <abstractions/nameservice>
|
|
||||||
|
|
||||||
capability net_bind_service,
|
|
||||||
capability setgid,
|
|
||||||
capability setuid,
|
|
||||||
capability dac_override,
|
|
||||||
capability net_admin, # for DHCP server
|
|
||||||
capability net_raw, # for DHCP server ping checks
|
|
||||||
network inet raw,
|
|
||||||
|
|
||||||
/etc/dnsmasq.conf r,
|
|
||||||
/etc/dnsmasq.d/ r,
|
|
||||||
/etc/dnsmasq.d/* r,
|
|
||||||
/etc/ethers r,
|
|
||||||
|
|
||||||
/usr/sbin/dnsmasq mr,
|
|
||||||
|
|
||||||
/{,var/}run/*dnsmasq*.pid w,
|
|
||||||
/{,var/}run/dnsmasq-forwarders.conf r,
|
|
||||||
/{,var/}run/dnsmasq/ r,
|
|
||||||
/{,var/}run/dnsmasq/* rw,
|
|
||||||
|
|
||||||
/var/lib/misc/dnsmasq.leases rw, # Required only for DHCP server usage
|
|
||||||
|
|
||||||
# for the read-only TFTP server
|
|
||||||
@{TFTP_DIR}/ r,
|
|
||||||
@{TFTP_DIR}/** r,
|
|
||||||
|
|
||||||
# libvirt lease and hosts files for dnsmasq
|
|
||||||
/var/lib/libvirt/dnsmasq/ r,
|
|
||||||
/var/lib/libvirt/dnsmasq/*.leases rw,
|
|
||||||
/var/lib/libvirt/dnsmasq/*.hostsfile r,
|
|
||||||
|
|
||||||
# libvirt pid files for dnsmasq
|
|
||||||
/{,var/}run/libvirt/network/ r,
|
|
||||||
/{,var/}run/libvirt/network/*.pid rw,
|
|
||||||
|
|
||||||
# NetworkManager integration
|
|
||||||
/{,var/}run/nm-dns-dnsmasq.conf r,
|
|
||||||
/{,var/}run/sendsigs.omit.d/*dnsmasq.pid w,
|
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
|
||||||
#include <local/usr.sbin.dnsmasq>
|
|
||||||
}
|
|
|
@ -12,6 +12,4 @@ args = parser.parse_args()
|
||||||
|
|
||||||
audit = aa_tools('audit', args)
|
audit = aa_tools('audit', args)
|
||||||
|
|
||||||
audit.check_profile_dir()
|
|
||||||
|
|
||||||
audit.act()
|
audit.act()
|
||||||
|
|
|
@ -12,6 +12,4 @@ args = parser.parse_args()
|
||||||
|
|
||||||
autodep = aa_tools('autodep', args)
|
autodep = aa_tools('autodep', args)
|
||||||
|
|
||||||
autodep.check_profile_dir()
|
|
||||||
|
|
||||||
autodep.act()
|
autodep.act()
|
|
@ -1,41 +1,14 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import os
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
import apparmor.aa as apparmor
|
from apparmor.tools import *
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Cleanup the profiles for the given programs')
|
parser = argparse.ArgumentParser(description='Cleanup the profiles for the given programs')
|
||||||
parser.add_argument('-d', type=str, help='path to profiles')
|
parser.add_argument('-d', type=str, help='path to profiles')
|
||||||
parser.add_argument('program', type=str, nargs='+', help='name of program')
|
parser.add_argument('program', type=str, nargs='+', help='name of program')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
profiling = args.program
|
clean = aa_tools('cleanprof', args)
|
||||||
profiledir = args.d
|
|
||||||
|
|
||||||
if profiledir:
|
|
||||||
apparmor.profile_dir = apparmor.get_full_path(profiledir)
|
|
||||||
if not os.path.isdir(apparmor.profile_dir):
|
|
||||||
raise apparmor.AppArmorException("%s is not a directory."%profiledir)
|
|
||||||
|
|
||||||
for p in sorted(profiling):
|
|
||||||
if not p:
|
|
||||||
continue
|
|
||||||
|
|
||||||
program = None
|
|
||||||
if os.path.exists(p):
|
|
||||||
program = apparmor.get_full_path(p).strip()
|
|
||||||
else:
|
|
||||||
which = apparmor.which(p)
|
|
||||||
if which:
|
|
||||||
program = apparmor.get_full_path(which)
|
|
||||||
|
|
||||||
if os.path.exists(program):
|
|
||||||
apparmor.read_profiles()
|
|
||||||
filename = apparmor.get_profile_filename(program)
|
|
||||||
if filename:
|
|
||||||
apparmor.write_profile_ui_feedback(program)
|
|
||||||
apparmor.reload_base(program)
|
|
||||||
else:
|
|
||||||
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.')%p)
|
|
||||||
|
|
||||||
|
clean.act()
|
|
@ -12,6 +12,4 @@ args = parser.parse_args()
|
||||||
|
|
||||||
complain = aa_tools('complain', args)
|
complain = aa_tools('complain', args)
|
||||||
|
|
||||||
complain.check_profile_dir()
|
|
||||||
|
|
||||||
complain.act()
|
complain.act()
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from apparmor.tools import *
|
from apparmor.tools import *
|
||||||
import apparmor.aa as apparmor
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Disable the profile for the given programs')
|
parser = argparse.ArgumentParser(description='Disable the profile for the given programs')
|
||||||
parser.add_argument('-d', type=str, help='path to profiles')
|
parser.add_argument('-d', type=str, help='path to profiles')
|
||||||
|
@ -13,8 +12,5 @@ args = parser.parse_args()
|
||||||
|
|
||||||
disable = aa_tools('disable', args)
|
disable = aa_tools('disable', args)
|
||||||
|
|
||||||
disable.check_profile_dir()
|
|
||||||
disable.check_disable_dir()
|
|
||||||
|
|
||||||
disable.act()
|
disable.act()
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,12 @@ from apparmor.tools import *
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Switch the given program to enforce mode')
|
parser = argparse.ArgumentParser(description='Switch the given program to enforce mode')
|
||||||
parser.add_argument('-d', type=str, help='path to profiles')
|
parser.add_argument('-d', type=str, help='path to profiles')
|
||||||
parser.add_argument('-r', '--remove', action='store_true', help='remove enforce mode')
|
parser.add_argument('-r', '--remove', action='store_true', help='switch to complain mode')
|
||||||
parser.add_argument('program', type=str, nargs='+', help='name of program')
|
parser.add_argument('program', type=str, nargs='+', help='name of program')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
# Flipping the remove flag since complain = !enforce
|
||||||
|
args.remove = not args.remove
|
||||||
|
|
||||||
enforce = aa_tools('enforce', args)
|
enforce = aa_tools('complain', args)
|
||||||
|
|
||||||
enforce.check_profile_dir()
|
|
||||||
|
|
||||||
enforce.act()
|
enforce.act()
|
||||||
|
|
0
Tools/aa-mergeprof.py
Normal file
0
Tools/aa-mergeprof.py
Normal file
|
@ -47,19 +47,19 @@ for pid in sorted(pids):
|
||||||
pname = '(%s)'%pname
|
pname = '(%s)'%pname
|
||||||
else:
|
else:
|
||||||
pname = ''
|
pname = ''
|
||||||
|
regex_interpreter = re.compile('^(/usr)?/bin/(python|perl|bash|dash|sh)$')
|
||||||
if not attr:
|
if not attr:
|
||||||
if re.search('^(/usr)?/bin/(python|perl|bash|sh)', prog):
|
if regex_interpreter.search(prog):
|
||||||
cmdline = re.sub('\x00', ' ', cmdline)
|
cmdline = re.sub('\x00', ' ', cmdline)
|
||||||
cmdline = re.sub('\s+$', '', cmdline).strip()
|
cmdline = re.sub('\s+$', '', cmdline).strip()
|
||||||
if 'perl' in cmdline:
|
|
||||||
print(cmdline)
|
|
||||||
apparmor.UI_Info(_('%s %s (%s) not confined\n')%(pid, prog, cmdline))
|
apparmor.UI_Info(_('%s %s (%s) not confined\n')%(pid, prog, cmdline))
|
||||||
else:
|
else:
|
||||||
if pname and pname[-1] == ')':
|
if pname and pname[-1] == ')':
|
||||||
pname += ' '
|
pname += ' '
|
||||||
apparmor.UI_Info(_('%s %s %snot confined\n')%(pid, prog, pname))
|
apparmor.UI_Info(_('%s %s %snot confined\n')%(pid, prog, pname))
|
||||||
else:
|
else:
|
||||||
if re.search('^(/usr)?/bin/(python|perl|bash|sh)', prog):
|
if regex_interpreter.search(prog):
|
||||||
cmdline = re.sub('\0', ' ', cmdline)
|
cmdline = re.sub('\0', ' ', cmdline)
|
||||||
cmdline = re.sub('\s+$', '', cmdline).strip()
|
cmdline = re.sub('\s+$', '', cmdline).strip()
|
||||||
apparmor.UI_Info(_("%s %s (%s) confined by '%s'\n")%(pid, prog, cmdline, attr))
|
apparmor.UI_Info(_("%s %s (%s) confined by '%s'\n")%(pid, prog, cmdline, attr))
|
||||||
|
|
160
apparmor/aa.py
160
apparmor/aa.py
|
@ -226,16 +226,46 @@ def complain(path):
|
||||||
prof_filename, name = name_to_prof_filename(path)
|
prof_filename, name = name_to_prof_filename(path)
|
||||||
if not prof_filename :
|
if not prof_filename :
|
||||||
fatal_error("Can't find %s" % path)
|
fatal_error("Can't find %s" % path)
|
||||||
UI_Info('Setting %s to complain mode.' % name)
|
set_complain(prof_filename, name)
|
||||||
change_profile_flags(prof_filename, 'complain')
|
|
||||||
|
|
||||||
def enforce(path):
|
def enforce(path):
|
||||||
"""Sets the profile to enforce mode if it exists"""
|
"""Sets the profile to enforce mode if it exists"""
|
||||||
prof_filename, name = name_to_prof_filename(path)
|
prof_filename, name = name_to_prof_filename(path)
|
||||||
if not prof_filename :
|
if not prof_filename :
|
||||||
fatal_error("Can't find %s" % path)
|
fatal_error("Can't find %s" % path)
|
||||||
UI_Info('Setting %s to enforce mode' % name)
|
set_enforce(prof_filename, name)
|
||||||
change_profile_flags(prof_filename, 'complain')
|
|
||||||
|
def set_complain(filename, program, ):
|
||||||
|
"""Sets the profile to complain mode"""
|
||||||
|
UI_Info('Setting %s to complain mode.' % program)
|
||||||
|
create_symlink('force-complain', filename)
|
||||||
|
change_profile_flags(filename, 'complain', True)
|
||||||
|
|
||||||
|
def set_enforce(filename, program):
|
||||||
|
"""Sets the profile to enforce mode"""
|
||||||
|
UI_Info('Setting %s to enforce mode' % program)
|
||||||
|
delete_symlink('force-complain', filename)
|
||||||
|
delete_symlink('disable', filename)
|
||||||
|
change_profile_flags(filename, 'complain', False)
|
||||||
|
|
||||||
|
def delete_symlink(subdir, filename):
|
||||||
|
path = filename
|
||||||
|
link = re.sub('^%s'%profile_dir, '%s/%s'%(profile_dir, subdir), path)
|
||||||
|
if link != path and os.path.islink(link):
|
||||||
|
os.remove(link)
|
||||||
|
|
||||||
|
def create_symlink(subdir, filename):
|
||||||
|
path = filename
|
||||||
|
bname = os.path.basename(filename)
|
||||||
|
if not bname:
|
||||||
|
raise AppArmorException(_('Unable to find basename for %s.')%filename)
|
||||||
|
link = re.sub('^%s'%profile_dir, '%s/%s'%(profile_dir, subdir), path)
|
||||||
|
link = link + '/%s'%bname
|
||||||
|
if not os.path.exists(link):
|
||||||
|
try:
|
||||||
|
os.symlink(filename, link)
|
||||||
|
except:
|
||||||
|
raise AppArmorException('Could not create %s symlink to %s.'%(link, filename))
|
||||||
|
|
||||||
def head(file):
|
def head(file):
|
||||||
"""Returns the first/head line of the file"""
|
"""Returns the first/head line of the file"""
|
||||||
|
@ -323,13 +353,7 @@ def create_new_profile(localfile):
|
||||||
local_profile = hasher()
|
local_profile = hasher()
|
||||||
local_profile[localfile]['flags'] = 'complain'
|
local_profile[localfile]['flags'] = 'complain'
|
||||||
local_profile[localfile]['include']['abstractions/base'] = 1
|
local_profile[localfile]['include']['abstractions/base'] = 1
|
||||||
#local_profile = {
|
|
||||||
# localfile: {
|
|
||||||
# 'flags': 'complain',
|
|
||||||
# 'include': {'abstraction/base': 1},
|
|
||||||
# 'allow': {'path': {}}
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
if os.path.isfile(localfile):
|
if os.path.isfile(localfile):
|
||||||
hashbang = head(localfile)
|
hashbang = head(localfile)
|
||||||
if hashbang.startswith('#!'):
|
if hashbang.startswith('#!'):
|
||||||
|
@ -529,7 +553,7 @@ def get_profile_flags(filename):
|
||||||
|
|
||||||
raise AppArmorException(_('%s contains no profile')%filename)
|
raise AppArmorException(_('%s contains no profile')%filename)
|
||||||
|
|
||||||
def change_profile_flags(filename, flag, remove=False):
|
def change_profile_flags(filename, flag, set_flag):
|
||||||
old_flags = get_profile_flags(filename)
|
old_flags = get_profile_flags(filename)
|
||||||
newflags = []
|
newflags = []
|
||||||
if old_flags != '':
|
if old_flags != '':
|
||||||
|
@ -542,16 +566,13 @@ def change_profile_flags(filename, flag, remove=False):
|
||||||
else:
|
else:
|
||||||
newflags = old_flags.split()
|
newflags = old_flags.split()
|
||||||
#newflags = [lambda x:x.strip(), oldflags]
|
#newflags = [lambda x:x.strip(), oldflags]
|
||||||
if flag in newflags:
|
|
||||||
if remove:
|
if set_flag:
|
||||||
newflags.remove(flag)
|
if flag not in newflags:
|
||||||
else:
|
|
||||||
if not remove:
|
|
||||||
if flag == '':
|
|
||||||
if 'complain' in newflags:
|
|
||||||
newflags.remove('complain')
|
|
||||||
else:
|
|
||||||
newflags.append(flag)
|
newflags.append(flag)
|
||||||
|
else:
|
||||||
|
if flag in newflags:
|
||||||
|
newflags.remove(flag)
|
||||||
|
|
||||||
newflags = ','.join(newflags)
|
newflags = ','.join(newflags)
|
||||||
|
|
||||||
|
@ -1838,30 +1859,7 @@ def ask_the_questions():
|
||||||
elif ans == 'CMD_GLOB':
|
elif ans == 'CMD_GLOB':
|
||||||
newpath = options[selected].strip()
|
newpath = options[selected].strip()
|
||||||
if not re_match_include(newpath):
|
if not re_match_include(newpath):
|
||||||
if newpath[-1] == '/':
|
newpath = glob_path(newpath)
|
||||||
if newpath[-4:] == '/**/' or newpath[-3:] == '/*/':
|
|
||||||
# /foo/**/ and /foo/*/ => /**/
|
|
||||||
newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', newpath) #re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', newpath)
|
|
||||||
elif re.search('/[^/]+\*\*[^/]*/$', newpath):
|
|
||||||
# /foo**/ and /foo**bar/ => /**/
|
|
||||||
newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', newpath)
|
|
||||||
elif re.search('/\*\*[^/]+/$', newpath):
|
|
||||||
# /**bar/ => /**/
|
|
||||||
newpath = re.sub('/\*\*[^/]+/$', '/**/', newpath)
|
|
||||||
else:
|
|
||||||
newpath = re.sub('/[^/]+/$', '/*/', newpath)
|
|
||||||
else:
|
|
||||||
if newpath[-3:] == '/**' or newpath[-2:] == '/*':
|
|
||||||
# /foo/** and /foo/* => /**
|
|
||||||
newpath = re.sub('/[^/]+/\*{1,2}$', '/**', newpath)
|
|
||||||
elif re.search('/[^/]*\*\*[^/]+$', newpath):
|
|
||||||
# /**foo and /foor**bar => /**
|
|
||||||
newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', newpath)
|
|
||||||
elif re.search('/[^/]+\*\*$', newpath):
|
|
||||||
# /foo** => /**
|
|
||||||
newpath = re.sub('/[^/]+\*\*$', '/**', newpath)
|
|
||||||
else:
|
|
||||||
newpath = re.sub('/[^/]+$', '/*', newpath)
|
|
||||||
|
|
||||||
if newpath not in options:
|
if newpath not in options:
|
||||||
options.append(newpath)
|
options.append(newpath)
|
||||||
|
@ -1872,23 +1870,7 @@ def ask_the_questions():
|
||||||
elif ans == 'CMD_GLOBEXT':
|
elif ans == 'CMD_GLOBEXT':
|
||||||
newpath = options[selected].strip()
|
newpath = options[selected].strip()
|
||||||
if not re_match_include(newpath):
|
if not re_match_include(newpath):
|
||||||
# match /**.ext and /*.ext
|
newpath = glob_path_withext(newpath)
|
||||||
match = re.search('/\*{1,2}(\.[^/]+)$', newpath)
|
|
||||||
if match:
|
|
||||||
# /foo/**.ext and /foo/*.ext => /**.ext
|
|
||||||
newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**'+match.groups()[0], newpath)
|
|
||||||
elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', newpath):
|
|
||||||
# /foo**.ext and /foo**bar.ext => /**.ext
|
|
||||||
match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', newpath)
|
|
||||||
newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**'+match.groups()[0], newpath)
|
|
||||||
elif re.search('/\*\*[^/]+\.[^/]+$', newpath):
|
|
||||||
# /**foo.ext => /**.ext
|
|
||||||
match = re.search('/\*\*[^/]+(\.[^/]+)$', newpath)
|
|
||||||
newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**'+match.groups()[0], newpath)
|
|
||||||
else:
|
|
||||||
match = re.search('(\.[^/]+)$', newpath)
|
|
||||||
if match:
|
|
||||||
newpath = re.sub('/[^/]+(\.[^/]+)$', '/*'+match.groups()[0], newpath)
|
|
||||||
|
|
||||||
if newpath not in options:
|
if newpath not in options:
|
||||||
options.append(newpath)
|
options.append(newpath)
|
||||||
|
@ -1984,6 +1966,55 @@ def ask_the_questions():
|
||||||
else:
|
else:
|
||||||
done = False
|
done = False
|
||||||
|
|
||||||
|
def glob_path(newpath):
|
||||||
|
"""Glob the given file path"""
|
||||||
|
if newpath[-1] == '/':
|
||||||
|
if newpath[-4:] == '/**/' or newpath[-3:] == '/*/':
|
||||||
|
# /foo/**/ and /foo/*/ => /**/
|
||||||
|
newpath = re.sub('/[^/]+/\*{1,2}/$', '/**/', newpath) #re.sub('/[^/]+/\*{1,2}$/', '/\*\*/', newpath)
|
||||||
|
elif re.search('/[^/]+\*\*[^/]*/$', newpath):
|
||||||
|
# /foo**/ and /foo**bar/ => /**/
|
||||||
|
newpath = re.sub('/[^/]+\*\*[^/]*/$', '/**/', newpath)
|
||||||
|
elif re.search('/\*\*[^/]+/$', newpath):
|
||||||
|
# /**bar/ => /**/
|
||||||
|
newpath = re.sub('/\*\*[^/]+/$', '/**/', newpath)
|
||||||
|
else:
|
||||||
|
newpath = re.sub('/[^/]+/$', '/*/', newpath)
|
||||||
|
else:
|
||||||
|
if newpath[-3:] == '/**' or newpath[-2:] == '/*':
|
||||||
|
# /foo/** and /foo/* => /**
|
||||||
|
newpath = re.sub('/[^/]+/\*{1,2}$', '/**', newpath)
|
||||||
|
elif re.search('/[^/]*\*\*[^/]+$', newpath):
|
||||||
|
# /**foo and /foor**bar => /**
|
||||||
|
newpath = re.sub('/[^/]*\*\*[^/]+$', '/**', newpath)
|
||||||
|
elif re.search('/[^/]+\*\*$', newpath):
|
||||||
|
# /foo** => /**
|
||||||
|
newpath = re.sub('/[^/]+\*\*$', '/**', newpath)
|
||||||
|
else:
|
||||||
|
newpath = re.sub('/[^/]+$', '/*', newpath)
|
||||||
|
return newpath
|
||||||
|
|
||||||
|
def glob_path_withext(newpath):
|
||||||
|
"""Glob given file path with extension"""
|
||||||
|
# match /**.ext and /*.ext
|
||||||
|
match = re.search('/\*{1,2}(\.[^/]+)$', newpath)
|
||||||
|
if match:
|
||||||
|
# /foo/**.ext and /foo/*.ext => /**.ext
|
||||||
|
newpath = re.sub('/[^/]+/\*{1,2}\.[^/]+$', '/**'+match.groups()[0], newpath)
|
||||||
|
elif re.search('/[^/]+\*\*[^/]*\.[^/]+$', newpath):
|
||||||
|
# /foo**.ext and /foo**bar.ext => /**.ext
|
||||||
|
match = re.search('/[^/]+\*\*[^/]*(\.[^/]+)$', newpath)
|
||||||
|
newpath = re.sub('/[^/]+\*\*[^/]*\.[^/]+$', '/**'+match.groups()[0], newpath)
|
||||||
|
elif re.search('/\*\*[^/]+\.[^/]+$', newpath):
|
||||||
|
# /**foo.ext => /**.ext
|
||||||
|
match = re.search('/\*\*[^/]+(\.[^/]+)$', newpath)
|
||||||
|
newpath = re.sub('/\*\*[^/]+\.[^/]+$', '/**'+match.groups()[0], newpath)
|
||||||
|
else:
|
||||||
|
match = re.search('(\.[^/]+)$', newpath)
|
||||||
|
if match:
|
||||||
|
newpath = re.sub('/[^/]+(\.[^/]+)$', '/*'+match.groups()[0], newpath)
|
||||||
|
return newpath
|
||||||
|
|
||||||
def delete_net_duplicates(netrules, incnetrules):
|
def delete_net_duplicates(netrules, incnetrules):
|
||||||
deleted = 0
|
deleted = 0
|
||||||
if incnetrules and netrules:
|
if incnetrules and netrules:
|
||||||
|
@ -2426,7 +2457,7 @@ def is_skippable_file(path):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def is_skippable_dir(path):
|
def is_skippable_dir(path):
|
||||||
if path in ['disable', 'cache', 'force-complain', 'lxc']:
|
if re.search('(disable|cache|force-complain|lxc)', path):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -2768,6 +2799,9 @@ def parse_profile_data(data, file, do_include):
|
||||||
elif re_match_include(line):
|
elif re_match_include(line):
|
||||||
# Include files
|
# Include files
|
||||||
include_name = re_match_include(line)
|
include_name = re_match_include(line)
|
||||||
|
if include_name.startswith('local/'):
|
||||||
|
profile_data[profile][hat]['localinclude'][include_name] = True
|
||||||
|
|
||||||
|
|
||||||
if profile:
|
if profile:
|
||||||
profile_data[profile][hat]['include'][include_name] = True
|
profile_data[profile][hat]['include'][include_name] = True
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import apparmor.aa as apparmor
|
import apparmor.aa as apparmor
|
||||||
|
@ -9,15 +8,19 @@ class aa_tools:
|
||||||
self.name = tool_name
|
self.name = tool_name
|
||||||
self.profiledir = args.d
|
self.profiledir = args.d
|
||||||
self.profiling = args.program
|
self.profiling = args.program
|
||||||
|
self.check_profile_dir()
|
||||||
|
|
||||||
if tool_name in ['audit', 'complain', 'enforce']:
|
if tool_name in ['audit', 'complain']:
|
||||||
self.remove = args.remove
|
self.remove = args.remove
|
||||||
elif tool_name == 'disable':
|
elif tool_name == 'disable':
|
||||||
self.revert = args.revert
|
self.revert = args.revert
|
||||||
self.disabledir = apparmor.profile_dir+'/disable'
|
self.disabledir = apparmor.profile_dir+'/disable'
|
||||||
|
self.check_disable_dir()
|
||||||
elif tool_name == 'autodep':
|
elif tool_name == 'autodep':
|
||||||
self.force = args.force
|
self.force = args.force
|
||||||
self.aa_mountpoint = apparmor.check_for_apparmor()
|
self.aa_mountpoint = apparmor.check_for_apparmor()
|
||||||
|
elif tool_name == 'cleanprof':
|
||||||
|
pass
|
||||||
|
|
||||||
def check_profile_dir(self):
|
def check_profile_dir(self):
|
||||||
if self.profiledir:
|
if self.profiledir:
|
||||||
|
@ -42,46 +45,72 @@ class aa_tools:
|
||||||
if which:
|
if which:
|
||||||
program = apparmor.get_full_path(which)
|
program = apparmor.get_full_path(which)
|
||||||
|
|
||||||
if os.path.exists(program):
|
if not os.path.exists(program):
|
||||||
|
apparmor.UI_Info(_('The given program cannot be found, please try with the fully qualified path name of the program: '))
|
||||||
|
program = apparmor.UI_GetString('', '')
|
||||||
|
|
||||||
|
apparmor.read_profiles()
|
||||||
|
|
||||||
|
if program and apparmor.profile_exists(program):#os.path.exists(program):
|
||||||
if self.name == 'autodep':
|
if self.name == 'autodep':
|
||||||
self.use_autodep(program)
|
self.use_autodep(program)
|
||||||
|
|
||||||
|
elif self.name == 'cleanprof':
|
||||||
|
self.clean_profile(program, p)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
apparmor.read_profiles()
|
|
||||||
filename = apparmor.get_profile_filename(program)
|
filename = apparmor.get_profile_filename(program)
|
||||||
|
|
||||||
if not os.path.isfile(filename) or apparmor.is_skippable_file(filename):
|
if not os.path.isfile(filename) or apparmor.is_skippable_file(filename):
|
||||||
continue
|
apparmor.UI_Info(_('Profile for %s not found, skipping')%p)
|
||||||
|
|
||||||
if self.name == 'enforce':
|
|
||||||
apparmor.UI_Info(_('Setting %s to enforce mode.\n')%program)
|
|
||||||
apparmor.change_profile_flags(filename, '', self.remove)
|
|
||||||
#apparmor.set_profile_flags(filename, '')
|
|
||||||
self.remove_symlinks(filename)
|
|
||||||
|
|
||||||
elif self.name == 'disable':
|
elif self.name == 'disable':
|
||||||
apparmor.UI_Info(_('Disabling %s.\n')%program)
|
|
||||||
if not self.revert:
|
if not self.revert:
|
||||||
|
apparmor.UI_Info(_('Disabling %s.\n')%program)
|
||||||
self.disable_profile(filename)
|
self.disable_profile(filename)
|
||||||
else:
|
else:
|
||||||
self.remove_disable_link(filename)
|
apparmor.UI_Info(_('Enabling %s.\n')%program)
|
||||||
else:
|
self.enable_profile(filename)
|
||||||
apparmor.UI_Info(_('Setting %s to %s mode.\n')%(program, self.name))
|
|
||||||
apparmor.change_profile_flags(filename, self.name, self.remove)
|
|
||||||
#apparmor.set_profile_flags(filename, self.name)
|
|
||||||
|
|
||||||
cmd_info = apparmor.cmd(['cat', filename, '|', apparmor.parser, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
|
elif self.name == 'audit':
|
||||||
|
if not self.remove:
|
||||||
|
apparmor.UI_Info(_('Setting %s to audit mode.\n')%program)
|
||||||
|
else:
|
||||||
|
apparmor.UI_Info(_('Removing audit mode from %s.\n')%program)
|
||||||
|
apparmor.change_profile_flags(filename, 'audit', self.remove)
|
||||||
|
|
||||||
|
elif self.name == 'complain':
|
||||||
|
if not self.remove:
|
||||||
|
apparmor.set_complain(filename, program)
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
apparmor.set_enforce(filename, program)
|
||||||
|
#apparmor.set_profile_flags(filename, self.name)
|
||||||
|
else:
|
||||||
|
# One simply does not walk in here!
|
||||||
|
raise apparmor.AppArmorException('Unknown tool.')
|
||||||
|
|
||||||
|
cmd_info = apparmor.cmd([apparmor.parser, filename, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
|
||||||
|
#cmd_info = apparmor.cmd(['cat', filename, '|', apparmor.parser, '-I%s'%apparmor.profile_dir, '-R 2>&1', '1>/dev/null'])
|
||||||
|
|
||||||
if cmd_info[0] != 0:
|
if cmd_info[0] != 0:
|
||||||
raise apparmor.AppArmorException(cmd_info[1])
|
raise apparmor.AppArmorException(cmd_info[1])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if '/' not in p:
|
if '/' not in p:
|
||||||
apparmor.UI_Info(_("Can't find %s in the system path list. If the name of the application is correct, please run 'which %s' as a user with correct PATH environment set up in order to find the fully-qualified path.")%(p, p))
|
apparmor.UI_Info(_("Can't find %s in the system path list. If the name of the application is correct, please run 'which %s' as a user with correct PATH environment set up in order to find the fully-qualified path.\nPlease use the full path as parameter")%(p, p))
|
||||||
else:
|
else:
|
||||||
apparmor.UI_Info(_("%s does not exist, please double-check the path.")%p)
|
apparmor.UI_Info(_("%s does not exist, please double-check the path.")%p)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def clean_profile(self, program, p):
|
||||||
|
filename = apparmor.get_profile_filename(program)
|
||||||
|
if filename:
|
||||||
|
apparmor.write_profile_ui_feedback(program)
|
||||||
|
apparmor.reload_base(program)
|
||||||
|
else:
|
||||||
|
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.')%p)
|
||||||
|
|
||||||
def use_autodep(self, program):
|
def use_autodep(self, program):
|
||||||
apparmor.check_qualifiers(program)
|
apparmor.check_qualifiers(program)
|
||||||
|
|
||||||
|
@ -92,37 +121,8 @@ class aa_tools:
|
||||||
if self.aa_mountpoint:
|
if self.aa_mountpoint:
|
||||||
apparmor.reload(program)
|
apparmor.reload(program)
|
||||||
|
|
||||||
def remove_symlinks(self, filename):
|
def enable_profile(self, filename):
|
||||||
# Remove symlink from profile_dir/force-complain
|
apparmor.delete_symlink('disable', filename)
|
||||||
complainlink = filename
|
|
||||||
complainlink = re.sub('^%s'%apparmor.profile_dir, '%s/force-complain'%apparmor.profile_dir, complainlink)
|
|
||||||
if os.path.exists(complainlink):
|
|
||||||
os.remove(complainlink)
|
|
||||||
|
|
||||||
# remove symlink in profile_dir/disable
|
|
||||||
disablelink = filename
|
|
||||||
disablelink = re.sub('^%s'%apparmor.profile_dir, '%s/disable'%apparmor.profile_dir, disablelink)
|
|
||||||
if os.path.exists(disablelink):
|
|
||||||
os.remove(disablelink)
|
|
||||||
|
|
||||||
def remove_disable_link(self, filename):
|
|
||||||
# Remove the file from disable dir
|
|
||||||
bname = os.path.basename(filename)
|
|
||||||
if not bname:
|
|
||||||
raise apparmor.AppArmorException(_('Unable to find basename for %s.')%filename)
|
|
||||||
|
|
||||||
link = '%s/%s'%(self.disabledir, bname)
|
|
||||||
if os.path.exists(link):
|
|
||||||
os.remove(link)
|
|
||||||
|
|
||||||
def disable_profile(self, filename):
|
def disable_profile(self, filename):
|
||||||
bname = os.path.basename(filename)
|
apparmor.create_symlink('disable', filename)
|
||||||
if not bname:
|
|
||||||
raise apparmor.AppArmorException(_('Unable to find basename for %s.')%filename)
|
|
||||||
|
|
||||||
link = '%s/%s'%(self.disabledir, bname)
|
|
||||||
if not os.path.exists(link):
|
|
||||||
try:
|
|
||||||
os.symlink(filename, link)
|
|
||||||
except:
|
|
||||||
raise apparmor.AppArmorException('Could not create %s symlink to %s.'%(link, filename))
|
|
Loading…
Add table
Reference in a new issue