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

As discussed a while ago, switch the utils (including their tests) to use python3 by default. While on it, drop usage of "env" to always get the system python3 instead of a random one that happens to live somewhere in $PATH. In practise, this patch doesn't change much - AFAIK openSUSE, Debian and Ubuntu already patch aa-* to use python3. Also add a note to README to officially deprecate Python 2.x. (I won't break Python 2.x support intentionally - unless some future change gives me a very good reason to finally drop Python 2.x support.) Acked-by: Seth Arnold <seth.arnold@canonical.com> (since 2016-08-23, but the commit had to wait for the FileRule series because it touches test-file.py)
177 lines
6.5 KiB
Python
Executable file
177 lines
6.5 KiB
Python
Executable file
#!/usr/bin/python3
|
|
# ----------------------------------------------------------------------
|
|
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
|
# Copyright (C) 2014 Canonical, Ltd.
|
|
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
|
|
#
|
|
# 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 unittest
|
|
from common_test import AATest, setup_all_loops
|
|
|
|
import apparmor.severity as severity
|
|
from apparmor.common import AppArmorException
|
|
|
|
class SeverityBaseTest(AATest):
|
|
|
|
def AASetup(self):
|
|
self.sev_db = severity.Severity('severity.db', 'unknown')
|
|
|
|
def _capability_severity_test(self, cap, expected_rank):
|
|
rank = self.sev_db.rank_capability(cap)
|
|
self.assertEqual(rank, expected_rank,
|
|
'expected rank %s, got %s' % (expected_rank, rank))
|
|
|
|
def _simple_severity_w_perm(self, path, perm, expected_rank):
|
|
rank = self.sev_db.rank_path(path, perm)
|
|
self.assertEqual(rank, expected_rank,
|
|
'expected rank %s, got %s' % (expected_rank, rank))
|
|
|
|
class SeverityTest(SeverityBaseTest):
|
|
tests = [
|
|
(['/usr/bin/whatis', 'x' ], 5),
|
|
(['/etc', 'x' ], 'unknown'),
|
|
(['/dev/doublehit', 'x' ], 0),
|
|
(['/dev/doublehit', 'rx' ], 4),
|
|
(['/dev/doublehit', 'rwx' ], 8),
|
|
(['/dev/tty10', 'rwx' ], 9),
|
|
(['/var/adm/foo/**', 'rx' ], 3),
|
|
(['/etc/apparmor/**', 'r' ], 6),
|
|
(['/etc/**', 'r' ], 'unknown'),
|
|
(['/usr/foo@bar', 'r' ], 'unknown'), ## filename containing @
|
|
(['/home/foo@bar', 'rw' ], 6), ## filename containing @
|
|
]
|
|
|
|
def _run_test(self, params, expected):
|
|
self._simple_severity_w_perm(params[0], params[1], expected) ## filename containing @
|
|
|
|
def test_invalid_rank(self):
|
|
with self.assertRaises(AppArmorException):
|
|
self._simple_severity_w_perm('unexpected_unput', 'rw', 6)
|
|
|
|
class SeverityTestCap(SeverityBaseTest):
|
|
tests = [
|
|
('KILL', 8),
|
|
('SETPCAP', 9),
|
|
('setpcap', 9),
|
|
('UNKNOWN', 'unknown'),
|
|
('K*', 'unknown'),
|
|
('__ALL__', 10),
|
|
]
|
|
|
|
def _run_test(self, params, expected):
|
|
self._capability_severity_test(params, expected)
|
|
|
|
rank = self.sev_db.rank_capability(params)
|
|
self.assertEqual(rank, expected, 'expected rank %s, got %s' % (expected, rank))
|
|
|
|
|
|
class SeverityVarsTest(SeverityBaseTest):
|
|
|
|
VARIABLE_DEFINITIONS = '''
|
|
@{HOME}=@{HOMEDIRS}/*/ /root/
|
|
@{HOMEDIRS}=/home/
|
|
# add another path to @{HOMEDIRS}
|
|
@{HOMEDIRS}+=/storage/
|
|
@{multiarch}=*-linux-gnu*
|
|
@{TFTP_DIR}=/var/tftp /srv/tftpboot
|
|
@{PROC}=/proc/
|
|
@{pid}={[1-9],[1-9][0-9],[1-9][0-9][0-9],[1-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9],[1-9][0-9][0-9][0-9][0-9][0-9]}
|
|
@{tid}=@{pid}
|
|
@{pids}=@{pid}
|
|
@{somepaths}=/home/foo/downloads @{HOMEDIRS}/foo/.ssh/
|
|
'''
|
|
|
|
def _init_tunables(self, content=''):
|
|
if not content:
|
|
content = self.VARIABLE_DEFINITIONS
|
|
|
|
self.rules_file = self.writeTmpfile('tunables', content)
|
|
|
|
self.sev_db.load_variables(self.rules_file)
|
|
|
|
def AATeardown(self):
|
|
self.sev_db.unload_variables()
|
|
|
|
tests = [
|
|
(['@{PROC}/sys/vm/overcommit_memory', 'r'], 6),
|
|
(['@{HOME}/sys/@{PROC}/overcommit_memory', 'r'], 4),
|
|
(['/overco@{multiarch}mmit_memory', 'r'], 'unknown'),
|
|
(['@{PROC}/sys/@{TFTP_DIR}/overcommit_memory', 'r'], 6),
|
|
(['@{somepaths}/somefile', 'r'], 7),
|
|
]
|
|
|
|
def _run_test(self, params, expected):
|
|
self._init_tunables()
|
|
self._simple_severity_w_perm(params[0], params[1], expected)
|
|
|
|
def test_include(self):
|
|
self._init_tunables('#include <file/not/found>') # including non-existing files doesn't raise an exception
|
|
|
|
self.assertTrue(True) # this test only makes sure that loading the tunables file works
|
|
|
|
def test_invalid_variable_add(self):
|
|
with self.assertRaises(AppArmorException):
|
|
self._init_tunables('@{invalid} += /home/')
|
|
|
|
def test_invalid_variable_double_definition(self):
|
|
with self.assertRaises(AppArmorException):
|
|
self._init_tunables('@{foo} = /home/\n@{foo} = /root/')
|
|
|
|
class SeverityDBTest(AATest):
|
|
def _test_db(self, contents):
|
|
self.db_file = self.writeTmpfile('severity.db', contents)
|
|
self.sev_db = severity.Severity(self.db_file)
|
|
return self.sev_db
|
|
|
|
tests = [
|
|
("CAP_LEASE 18\n" , AppArmorException), # out of range
|
|
("CAP_LEASE -1\n" , AppArmorException), # out of range
|
|
("/etc/passwd* 0 4\n" , AppArmorException), # insufficient vals
|
|
("/etc/passwd* 0 4 5 6\n" , AppArmorException), # too many vals
|
|
("/etc/passwd* -2 4 6\n" , AppArmorException), # out of range
|
|
("/etc/passwd* 12 4 6\n" , AppArmorException), # out of range
|
|
("/etc/passwd* 2 -4 6\n" , AppArmorException), # out of range
|
|
("/etc/passwd 2 14 6\n" , AppArmorException), # out of range
|
|
("/etc/passwd 2 4 -12\n" , AppArmorException), # out of range
|
|
("/etc/passwd 2 4 4294967297\n" , AppArmorException), # out of range
|
|
("garbage line\n" , AppArmorException),
|
|
]
|
|
|
|
def _run_test(self, params, expected):
|
|
with self.assertRaises(expected):
|
|
self._test_db(params)
|
|
|
|
def test_simple_db(self):
|
|
self._test_db('''
|
|
CAP_LEASE 8
|
|
/etc/passwd* 4 8 0
|
|
''')
|
|
|
|
def test_cap_val_max_range(self):
|
|
self._test_db("CAP_LEASE 10\n")
|
|
|
|
def test_cap_val_min_range(self):
|
|
self._test_db("CAP_LEASE 0\n")
|
|
|
|
def test_invalid_db(self):
|
|
self.assertRaises(AppArmorException, severity.Severity, 'severity_broken.db')
|
|
|
|
def test_nonexistent_db(self):
|
|
self.assertRaises(IOError, severity.Severity, 'severity.db.does.not.exist')
|
|
|
|
def test_no_arg_to_severity(self):
|
|
with self.assertRaises(AppArmorException):
|
|
severity.Severity()
|
|
|
|
setup_all_loops(__name__)
|
|
if __name__ == '__main__':
|
|
unittest.main(verbosity=2)
|