2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 06:16:03 +00:00

Merge from main branch

This commit is contained in:
Gregor Dschung
2012-11-07 12:02:57 +01:00
8 changed files with 304 additions and 37 deletions

14
README
View File

@@ -146,6 +146,20 @@ For details on structure and adding tests, see libraries/libapparmor/README.
$ cd libraries/libapparmor
$ make check
Utils
-----
There are some simple tests available, including basic perl syntax
checks for the perl modules and executables. There are also minimal
checks on the python utilities and python-based tests in the test/
subdirectory.
$ cd utils
$ make check
The aa-decode utility to be tested can be overridden by
setting up environment variable APPARMOR_DECODE; e.g.:
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
Profile checks
--------------
A basic consistency check to ensure that the parser and aa-logprof parse

View File

@@ -36,13 +36,13 @@ error_output: $(PARSER)
@echo "Error Output: PASS"
parser_sanity: $(PARSER)
$(Q)${PROVE} ${PROVE_ARG} ${TESTS}
$(Q)LANG=C APPARMOR_PARSER="$(PARSER)" ${PROVE} ${PROVE_ARG} ${TESTS}
caching: $(PARSER)
LANG=C ./caching.sh
LANG=C APPARMOR_PARSER="$(PARSER)" ./caching.sh
minimize: $(PARSER)
LANG=C ./minimize.sh
LANG=C APPARMOR_PARSER="$(PARSER)" ./minimize.sh
$(PARSER):
make -C $(PARSER_DIR) $(PARSER_BIN)

View File

@@ -9,6 +9,10 @@ There is a user configuration file 'uservars.conf'. If you wish to test
against a different parser, or use a different set of profiles for the
simple.pl test, you can change those settings in 'uservars.conf'.
You can also override which parser is used through make by specifying
the PARSER veriable. For example, to run the tests on the system parser,
run 'make PARSER=/sbin/apparmor_parser'.
Adding to the testsuite
-----------------------

View File

@@ -10,6 +10,8 @@ if [ ! -d /sys/kernel/security/apparmor ]; then
exit 0
fi
APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
# fake base directory
basedir=$(mktemp -d -t aa-cache-XXXXXX)
trap "rm -rf $basedir" EXIT
@@ -33,19 +35,19 @@ fi
rm -f $basedir/test1 $basedir/test2
echo -n "Profiles are not cached by default: "
../apparmor_parser $ARGS -q -r $basedir/$profile
${APPARMOR_PARSER} $ARGS -q -r $basedir/$profile
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
echo -n "Profiles are not cached when using --skip-cache: "
../apparmor_parser $ARGS -q --write-cache --skip-cache -r $basedir/$profile
${APPARMOR_PARSER} $ARGS -q --write-cache --skip-cache -r $basedir/$profile
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
sleep $timeout
echo -n "Profiles are cached when requested: "
../apparmor_parser $ARGS -q --write-cache -r $basedir/$profile
${APPARMOR_PARSER} $ARGS -q --write-cache -r $basedir/$profile
[ ! -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile does not exist)" && exit 1
echo "ok"
@@ -80,22 +82,22 @@ fi
echo "ok"
echo -n "Cache is loaded when it exists and features match: "
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache is not loaded when skipping is requested: "
../apparmor_parser $ARGS -v --skip-read-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
../apparmor_parser $ARGS -v --skip-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v --skip-read-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v --skip-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when features do not match cache: "
echo -n "monkey" > $basedir/cache/.features
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache writing is skipped when features do not match and not cleared: "
rm $basedir/cache/$profile
../apparmor_parser $ARGS -v --write-cache --skip-bad-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v --write-cache --skip-bad-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
[ -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile exists)" && exit 1
echo "ok"
@@ -104,7 +106,7 @@ rm -f $basedir/cache/$profile || true
echo -n "monkey" > $basedir/cache/.features
echo -n "monkey" > $basedir/cache/$profile
echo -n "monkey" > $basedir/cache/monkey
../apparmor_parser $ARGS -v --write-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "Cache clear setup FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v --write-cache -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "Cache clear setup FAIL"; exit 1; }
echo -n "Cache clear updates features: "
echo -n "monkey" | diff -q $basedir/cache/.features - | grep -q 'differ' || { echo "FAIL"; exit 1; }
echo "ok"
@@ -122,7 +124,7 @@ echo -n "monkey" > $basedir/cache/.features
echo -n "monkey" > $basedir/cache/$profile
echo -n "monkey" > $basedir/cache/monkey
echo -n "Cache purge remove profiles unconditionally: "
../apparmor_parser $ARGS -v --purge-cache -r $basedir/$profile || { echo "Cache purge setup FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v --purge-cache -r $basedir/$profile || { echo "Cache purge setup FAIL"; exit 1; }
[ -f $basedir/cache/.features ] && { echo "FAIL"; exit 1; }
[ -f $basedir/cache/$profile ] && { echo "FAIL"; exit 1; }
[ -f $basedir/cache/monkey ] && { echo "FAIL"; exit 1; }
@@ -131,25 +133,25 @@ echo "ok"
echo -n "Profiles are cached when requested (again): "
rm -f $basedir/cache/.features || true
rm -f $basedir/cache/$profile || true
../apparmor_parser $ARGS -q --write-cache -r $basedir/$profile
${APPARMOR_PARSER} $ARGS -q --write-cache -r $basedir/$profile
[ ! -f $basedir/cache/$profile ] && echo "FAIL ($basedir/cache/$profile does not exist)" && exit 1
echo "ok"
echo -n "Cache reading is skipped when profile is newer: "
sleep $timeout
touch $basedir/$profile
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache is used when cache is newer: "
sleep $timeout
touch $basedir/cache/$profile
../apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
${APPARMOR_PARSER} $ARGS -v -r $basedir/$profile | grep -q 'Cached reload succeeded' || { echo "FAIL"; exit 1; }
echo "ok"
echo -n "Cache reading is skipped when parser is newer: "
mkdir $basedir/parser
cp ../apparmor_parser $basedir/parser/
cp ${APPARMOR_PARSER} $basedir/parser/
$basedir/parser/apparmor_parser $ARGS -v -r $basedir/$profile | grep -q 'Replacement succeeded for' || { echo "FAIL"; exit 1; }
echo "ok"

View File

@@ -1,5 +1,8 @@
#!/bin/bash
#
APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
# Format of -D dfa-states
# dfa-states output is split into 2 parts:
# the accept state infomation
@@ -75,7 +78,7 @@
# {a} (0x 40030/0/0/0)
echo -n "Minimize profiles basic perms "
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
echo "failed"
exit 1;
fi
@@ -90,7 +93,7 @@ echo "ok"
# {9} (0x 12804a/0/2800a/0)
# {c} (0x 40030/0/0/0)
echo -n "Minimize profiles audit perms "
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
echo "failed"
exit 1;
fi
@@ -109,7 +112,7 @@ echo "ok"
# {c} (0x 40030/0/0/0)
echo -n "Minimize profiles deny perms "
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 6 ] ; then
echo "failed"
exit 1;
fi
@@ -127,7 +130,7 @@ echo "ok"
# {c} (0x 40030/0/0/0)
echo -n "Minimize profiles audit deny perms "
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 5 ] ; then
if [ `echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, audit deny /** w, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 5 ] ; then
echo "failed"
exit 1;
fi
@@ -159,7 +162,7 @@ echo "ok"
#
echo -n "Minimize profiles xtrans "
if [ `echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
if [ `echo "/t { /b px, /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
echo "failed"
exit 1;
fi
@@ -167,7 +170,7 @@ echo "ok"
# same test as above + audit
echo -n "Minimize profiles audit xtrans "
if [ `echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
if [ `echo "/t { /b px, audit /* Pixr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 3 ] ; then
echo "failed"
exit 1;
fi
@@ -180,7 +183,7 @@ echo "ok"
# {3} (0x 0/fe17f85/0/14005)
echo -n "Minimize profiles deny xtrans "
if [ `echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
if [ `echo "/t { /b px, deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 1 ] ; then
echo "failed"
exit 1;
fi
@@ -192,7 +195,7 @@ echo "ok"
# {3} (0x 0/fe17f85/0/0)
echo -n "Minimize profiles audit deny xtrans "
if [ `echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ../apparmor_parser -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 0 ] ; then
if [ `echo "/t { /b px, audit deny /* xr, /a Cx -> foo, }" | ${APPARMOR_PARSER} -QT -O minimize -D dfa-states 2>&1 | grep -v '<==' | grep '^{.*} (.*)$' | wc -l` -ne 0 ] ; then
echo "failed"
exit 1;
fi

View File

@@ -8,7 +8,7 @@ use Getopt::Long;
use Test::More;
my %config;
$config{'parser'} = "/sbin/subdomain_parser";
$config{'parser'} = "/sbin/apparmor_parser";
$config{'profiledir'} = "./simple_tests/";
$config{'timeout'} = 120; # in seconds
@@ -30,6 +30,12 @@ sub usage {
&usage if ($help);
read_config();
# let environment variable override config file, for use in automated
# test suites
if ($ENV{APPARMOR_PARSER}) {
$config{'parser'} = $ENV{APPARMOR_PARSER};
}
# Override config file profile location when passed on command line
if (@ARGV >= 1) {
$config{'profiledir'} = shift;
@@ -68,6 +74,16 @@ sub test_profile {
my $result = 0;
my $child;
$child = open(PARSER, "|-");
if ($child == 0) {
# child
open(STDOUT, ">/dev/null") or die "Failed to redirect STDOUT";
open(STDERR, ">/dev/null") or die "Failed to redirect STDERR";
exec("$config{'parser'}", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
# noreturn
}
# parent
eval {
local $SIG{ALRM} = sub {
$result = 1;
@@ -77,19 +93,9 @@ sub test_profile {
alarm $config{'timeout'};
$child = open(PARSER, "|-");
if ($child == 0) {
# child
open(STDOUT, ">/dev/null") or die "Failed to redirect STDOUT";
open(STDERR, ">/dev/null") or die "Failed to redirect STDERR";
exec("$config{'parser'}", "-S", "-I", "$config{'includedir'}") or die "Bail out! couldn't open parser";
# noreturn
}
# parent
open(PROFILE, $profile) or die "Bail out! couldn't open profile $profile";
while (<PROFILE>) {
if (/^#=DESCRIPTION\s*(.*)/) {
if (/^#=DESCRIPTION\s*(.*)/i) {
$description = $1;
} elsif (/^#=EXRESULT\s*(\w+)/) {
if ($1 eq "PASS") {

View File

@@ -0,0 +1,35 @@
# Last Modified: Mon Mar 26 20:28:18 2012
#include <tunables/global>
/usr/sbin/winbindd {
#include <abstractions/base>
#include <abstractions/nameservice>
/etc/samba/dhcp.conf r,
/etc/samba/passdb.tdb rwk,
/etc/samba/secrets.tdb rwk,
@{PROC}/sys/kernel/core_pattern r,
/tmp/.winbindd/ w,
/usr/lib*/samba/idmap/*.so mr,
/usr/lib*/samba/nss_info/*.so mr,
/usr/sbin/winbindd mr,
/var/lib/samba/account_policy.tdb rwk,
/var/lib/samba/gencache.tdb rwk,
/var/lib/samba/gencache_notrans.tdb rwk,
/var/lib/samba/group_mapping.tdb rwk,
/var/lib/samba/messages.tdb rwk,
/var/lib/samba/netsamlogon_cache.tdb rwk,
/var/lib/samba/serverid.tdb rwk,
/var/lib/samba/winbindd_cache.tdb rwk,
/var/lib/samba/winbindd_privileged/pipe w,
/var/log/samba/cores/ rw,
/var/log/samba/cores/winbindd/ rw,
/var/log/samba/cores/winbindd/** rw,
/var/log/samba/log.wb-* w,
/var/log/samba/log.winbindd rw,
/{var/,}run/samba/winbindd.pid rwk,
# Site-specific additions and overrides. See local/README for details.
#include <local/usr.sbin.winbindd>
}

203
utils/test/test-aa-decode.py Executable file
View File

@@ -0,0 +1,203 @@
#! /usr/bin/env python
# ------------------------------------------------------------------
#
# Copyright (C) 2011-2012 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.
#
# ------------------------------------------------------------------
import os
import signal
import subprocess
import tempfile
import unittest
# The locationg of the aa-decode utility can be overridden by setting
# the APPARMOR_DECODE environment variable; this is useful for running
# these tests in an installed environment
aadecode_bin = "./aa-decode"
# http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html
# This is needed so that the subprocesses that produce endless output
# actually quit when the reader goes away.
def subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
# non-Python subprocesses expect.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def cmd(command, input = None, stderr = subprocess.STDOUT, stdout = subprocess.PIPE, stdin = None, timeout = None):
'''Try to execute given command (array) and return its stdout, or return
a textual error if it failed.'''
try:
sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=True, preexec_fn=subprocess_setup)
except OSError as e:
return [127, str(e)]
out, outerr = sp.communicate(input)
# Handle redirection of stdout
if out == None:
out = b''
# Handle redirection of stderr
if outerr == None:
outerr = b''
return [sp.returncode, out.decode('utf-8') + outerr.decode('utf-8')]
def mkstemp_fill(contents, suffix='', prefix='tst-aadecode-', dir=None):
'''As tempfile.mkstemp does, return a (file, name) pair, but with prefilled contents.'''
handle, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir)
os.close(handle)
handle = open(name, "w+")
handle.write(contents)
handle.flush()
handle.seek(0)
return handle, name
class AADecodeTest(unittest.TestCase):
def setUp(self):
self.tmpfile = None
def tearDown(self):
if self.tmpfile and os.path.exists(self.tmpfile):
os.remove(self.tmpfile)
def test_help(self):
'''Test --help argument'''
expected = 0
rc, report = cmd([aadecode_bin, "--help"])
result = 'Got exit code %d, expected %d\n' % (rc, expected)
self.assertEqual(expected, rc, result + report)
def _run_file_test(self, content, expected_list):
'''test case helper function; takes log content and a list of
expected strings as arguments'''
expected = 0
(f, self.tmpfile) = mkstemp_fill(content)
rc, report = cmd([aadecode_bin], stdin=f)
result = 'Got exit code %d, expected %d\n' % (rc, expected)
self.assertEqual(expected, rc, result + report)
for expected_string in expected_list:
result = 'could not find expected %s in output:\n' % (expected_string)
self.assertIn(expected_string, report, result + report)
f.close()
def test_simple_decode(self):
'''Test simple decode on command line'''
expected = 0
expected_output = 'Decoded: /tmp/foo bar'
test_code = '2F746D702F666F6F20626172'
rc, report = cmd([aadecode_bin, test_code])
result = 'Got exit code %d, expected %d\n' % (rc, expected)
self.assertEqual(expected, rc, result + report)
result = 'Got output "%s", expected "%s"\n' % (report, expected_output)
self.assertIn(expected_output, report, result + report)
def test_simple_filter(self):
'''test simple decoding of the name argument'''
expected_string = 'name="/tmp/foo bar"'
content = \
'''type=AVC msg=audit(1348982151.183:2934): apparmor="DENIED" operation="open" parent=30751 profile="/usr/lib/firefox/firefox{,*[^s] [^h]}" name=2F746D702F666F6F20626172 pid=30833 comm="plugin-containe" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
'''
self._run_file_test(content, [expected_string])
def test_simple_multiline(self):
'''test simple multiline decoding of the name argument'''
expected_strings = ['ses=4294967295 new ses=2762',
'name="/tmp/foo bar"',
'name="/home/steve/tmp/my test file"']
content = \
''' type=LOGIN msg=audit(1348980001.155:2925): login pid=17875 uid=0 old auid=4294967295 new auid=0 old ses=4294967295 new ses=2762
type=AVC msg=audit(1348982151.183:2934): apparmor="DENIED" operation="open" parent=30751 profile="/usr/lib/firefox/firefox{,*[^s] [^h]}" name=2F746D702F666F6F20626172 pid=30833 comm="plugin-containe" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
type=AVC msg=audit(1348982148.195:2933): apparmor="DENIED" operation="file_lock" parent=5490 profile="/usr/lib/firefox/firefox{,*[^s][^h]}" name=2F686F6D652F73746576652F746D702F6D7920746573742066696C65 pid=30737 comm="firefox" requested_mask="k" denied_mask="k" fsuid=1000 ouid=1000
'''
self._run_file_test(content, expected_strings)
def test_simple_profile(self):
'''test simple decoding of the profile argument'''
'''Example take from LP: #897957'''
expected_strings = ['name="/lib/x86_64-linux-gnu/libdl-2.13.so"',
'profile="/test space"']
content = \
'''[289763.843292] type=1400 audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=2F74657374207370616365 name="/lib/x86_64-linux-gnu/libdl-2.13.so" pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
'''
self._run_file_test(content, expected_strings)
def test_simple_profile2(self):
'''test simple decoding of name and profile argument'''
'''Example take from LP: #897957'''
expected_strings = ['name="/home/steve/tmp/my test file"',
'profile="/home/steve/tmp/my prog.sh"']
content = \
'''type=AVC msg=audit(1349805073.402:6857): apparmor="DENIED" operation="mknod" parent=5890 profile=2F686F6D652F73746576652F746D702F6D792070726F672E7368 name=2F686F6D652F73746576652F746D702F6D7920746573742066696C65 pid=5891 comm="touch" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
'''
self._run_file_test(content, expected_strings)
def test_simple_embedded_carat(self):
'''test simple decoding of embedded ^ in files'''
expected_strings = ['name="/home/steve/tmp/my test ^file"']
content = \
'''type=AVC msg=audit(1349805073.402:6857): apparmor="DENIED" operation="mknod" parent=5890 profile="/usr/bin/test_profile" name=2F686F6D652F73746576652F746D702F6D792074657374205E66696C65 pid=5891 comm="touch" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
'''
self._run_file_test(content, expected_strings)
def test_simple_embedded_backslash_carat(self):
'''test simple decoding of embedded \^ in files'''
expected_strings = ['name="/home/steve/tmp/my test \^file"']
content = \
'''type=AVC msg=audit(1349805073.402:6857): apparmor="DENIED" operation="mknod" parent=5890 profile="/usr/bin/test_profile" name=2F686F6D652F73746576652F746D702F6D792074657374205C5E66696C65 pid=5891 comm="touch" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
'''
self._run_file_test(content, expected_strings)
def test_simple_embedded_singlequote(self):
'''test simple decoding of embedded \' in files'''
expected_strings = ['name="/home/steve/tmp/my test \'file"']
content = \
'''type=AVC msg=audit(1349805073.402:6857): apparmor="DENIED" operation="mknod" parent=5890 profile="/usr/bin/test_profile" name=2F686F6D652F73746576652F746D702F6D792074657374202766696C65 pid=5891 comm="touch" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
'''
self._run_file_test(content, expected_strings)
def test_simple_encoded_nonpath_profiles(self):
'''test simple decoding of nonpath profiles'''
expected_strings = ['name="/lib/x86_64-linux-gnu/libdl-2.13.so"',
'profile="test space"']
content = \
'''[289763.843292] type=1400 audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=74657374207370616365 name="/lib/x86_64-linux-gnu/libdl-2.13.so" pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
'''
self._run_file_test(content, expected_strings)
#
# Main
#
if __name__ == '__main__':
if 'APPARMOR_DECODE' in os.environ:
aadecode_bin = os.environ['APPARMOR_DECODE']
unittest.main()