Commit 6d34893d authored by Steve Beattie's avatar Steve Beattie

utils: add limited support for af_unix rules

This patch adds limited support for af_unix rules in the python
utilities, of the "don't touch them, but don't throw a python backtrace
when coming across them, either" variety. Testcases are added as well.
Signed-off-by: Steve Beattie's avatarSteve Beattie <>
Acked-by: Christian Boltz's avatarChristian Boltz <>
parent 9e4c01f8
......@@ -2636,6 +2636,7 @@ RE_PROFILE_MOUNT = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?((mount|remount
RE_PROFILE_SIGNAL = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?(signal\s*,|signal\s+[^#]*\s*,)\s*(#.*)?$')
RE_PROFILE_PTRACE = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?(ptrace\s*,|ptrace\s+[^#]*\s*,)\s*(#.*)?$')
RE_PROFILE_PIVOT_ROOT = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?(pivot_root\s*,|pivot_root\s+[^#]*\s*,)\s*(#.*)?$')
RE_PROFILE_UNIX = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?(unix\s*,|unix\s+[^#]*\s*,)\s*(#.*)?$')
# match anything that's not " or #, or matching quotes with anything except quotes inside
__re_no_or_quoted_hash = '([^#"]|"[^"]*")*'
......@@ -3110,6 +3111,28 @@ def parse_profile_data(data, file, do_include):
profile_data[profile][hat][allow]['pivot_root'] = pivot_root_rules
matches =
if not profile:
raise AppArmorException(_('Syntax Error: Unexpected unix entry found in file: %s line: %s') % (file, lineno + 1))
audit = False
if matches[0]:
audit = True
allow = 'allow'
if matches[1] and matches[1].strip() == 'deny':
allow = 'deny'
unix = matches[2].strip()
unix_rule = parse_unix_rule(unix)
unix_rule.audit = audit
unix_rule.deny = (allow == 'deny')
unix_rules = profile_data[profile][hat][allow].get('unix', list())
profile_data[profile][hat][allow]['unix'] = unix_rules
matches =
......@@ -3220,6 +3243,10 @@ def parse_pivot_root_rule(line):
# XXX Do real parsing here
return aarules.Raw_Pivot_Root_Rule(line)
def parse_unix_rule(line):
# XXX Do real parsing here
return aarules.Raw_Unix_Rule(line)
def separate_vars(vs):
"""Returns a list of all the values for a variable"""
data = []
......@@ -44,6 +44,18 @@ class DBUS_Rule(object):
out += ','
return out
class _Raw_Rule(object):
audit = False
deny = False
def __init__(self, rule):
self.rule = rule
def serialize(self):
return "%s%s%s" % ('audit ' if self.audit else '',
'deny ' if self.deny else '',
class Raw_DBUS_Rule(object):
audit = False
deny = False
......@@ -103,3 +115,6 @@ class Raw_Pivot_Root_Rule(object):
return "%s%s%s" % ('audit ' if self.audit else '',
'deny ' if self.deny else '',
class Raw_Unix_Rule(_Raw_Rule):
......@@ -58,6 +58,12 @@ regex_has_comma_testcases = [
('pivot_root /old new%s', 'pivot_root with new'),
('pivot_root /old /new -> child%s', 'pivot_root with child'),
('unix%s', 'bare unix'),
('unix create%s', 'simple unix'),
('peer=(addr=@abad1dea,label=a_profile) %s ', 'peer parens and comma'),
('type=stream%s', 'unix type'),
('unix (connect, receive, send)%s', 'unix perms'),
# the following fail due to inadequacies in the regex
# ('dbus (r, w, %s', 'incomplete dbus action'),
# ('member="{Hello,AddMatch,RemoveMatch, %s', 'incomplete {} regex'), # also invalid policy
......@@ -334,6 +340,31 @@ class AARegexPivotRoot(unittest.TestCase):
('pivot_rootbeer /new, # comment', False),
class AARegexUnix(unittest.TestCase):
'''Tests for RE_PROFILE_UNIX'''
def setUp(self):
self.regex = aa.RE_PROFILE_UNIX
tests = [
(' unix,', (None, None, 'unix,', None)),
(' audit unix,', ('audit', None, 'unix,', None)),
(' unix accept,', (None, None, 'unix accept,', None)),
(' allow unix connect,', (None, 'allow', 'unix connect,', None)),
(' audit allow unix bind,', ('audit', 'allow', 'unix bind,', None)),
(' deny unix bind,', (None, 'deny', 'unix bind,', None)),
('unix peer=(label=@{profile_name}),',
(None, None, 'unix peer=(label=@{profile_name}),', None)),
('unix (receive) peer=(label=unconfined),',
(None, None, 'unix (receive) peer=(label=unconfined),', None)),
(' unix (getattr, shutdown) peer=(addr=none),',
(None, None, 'unix (getattr, shutdown) peer=(addr=none),', None)),
('unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),',
(None, None, 'unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/dbus-*"),', None)),
('unixlike', False),
('deny unixlike,', False),
if __name__ == '__main__':
verbosity = 2
......@@ -345,7 +376,7 @@ if __name__ == '__main__':
for tests in (AARegexCapability, AARegexPath, AARegexBareFile,
AARegexDbus, AARegexMount,
AARegexDbus, AARegexMount, AARegexUnix,
AARegexSignal, AARegexPtrace, AARegexPivotRoot):
#! /usr/bin/env python
# ------------------------------------------------------------------
# Copyright (C) 2014 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 apparmor.aa as aa
import unittest
class AAParseUnixTest(unittest.TestCase):
def _test_parse_unix_rule(self, rule):
unix = aa.parse_unix_rule(rule)
self.assertEqual(rule, unix.serialize(),
'ptrace object returned "%s", expected "%s"' % (unix.serialize(), rule))
def test_parse_plain_unix_rule(self):
def test_parse_r_unix_rule(self):
self._test_parse_unix_rule('unix r,')
def test_parse_w_unix_rule(self):
self._test_parse_unix_rule('unix w,')
def test_parse_rw_unix_rule(self):
self._test_parse_unix_rule('unix rw,')
def test_parse_send_unix_rule(self):
self._test_parse_unix_rule('unix send,')
def test_parse_receive_unix_rule(self):
self._test_parse_unix_rule('unix receive,')
def test_parse_r_paren_unix_rule(self):
self._test_parse_unix_rule('unix (r),')
def test_parse_w_paren_unix_rule(self):
self._test_parse_unix_rule('unix (w),')
def test_parse_rw_paren_unix_rule(self):
self._test_parse_unix_rule('unix (rw),')
def test_parse_send_paren_unix_rule(self):
self._test_parse_unix_rule('unix (send),')
def test_parse_receive_paren_unix_rule(self):
self._test_parse_unix_rule('unix (receive),')
def test_parse_complex_unix_rule(self):
self._test_parse_unix_rule('unix (connect, receive, send) type=stream peer=(label=unconfined,addr="@/tmp/.X11-unix/X[0-9]*"),')
if __name__ == '__main__':
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment