Compare commits

..

No commits in common. "factory" and "devel" have entirely different histories.

14 changed files with 973 additions and 0 deletions

View File

@ -0,0 +1,26 @@
commit cabd88a94055d2a7b876758d36fe559a6b728f45
Author: Christian Boltz <apparmor@cboltz.de>
Date: Sat May 25 13:12:49 2024 +0200
Fix aa-remove-unknown for 'unconfined' profiles
Without this patch, aa-remove-unknown uses 'profile_name (unconfined)'
when trying to unload unconfined profiles, which fails for obvious
reasons with (picking a random example)
Removing 'busybox (unconfined)'
/sbin/aa-remove-unknown: line 112: echo: write error: No such file or directory
diff --git a/utils/aa-remove-unknown b/utils/aa-remove-unknown
index 0e00d6a03..983d23727 100755
--- a/utils/aa-remove-unknown
+++ b/utils/aa-remove-unknown
@@ -89,7 +89,7 @@ LOADED_PROFILES=$("$PARSER" -N $PROFILE_DIRS) || {
echo "$LOADED_PROFILES" | awk '
BEGIN {
while (getline < "'${PROFILES}'" ) {
- str = sub(/ \((enforce|complain)\)$/, "", $0);
+ str = sub(/ \((enforce|complain|unconfined)\)$/, "", $0);
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
arr[$str] = $str
}

3
apparmor-v4.0.1.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b0d72cedc48e533d189ea415bde721ad597101c77fa398fdd2858ec4f58f7e26
size 6984984

View File

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQJOBAABCgA4FiEEPs3Lpfs00lSWHMU/ZonmTj02ZLsFAmYYxToaHGFwcGFybW9y
QGxpc3RzLnVidW50dS5jb20ACgkQZonmTj02ZLuLfBAA1lpdyEcNhLvw0Ff0rkt7
Zoj/TgxYal/6FwuJ10eUnHrZhwGjhiX8zin2gbZaM7X8kscsSwelEqquSliu6lqp
O63B8cGa6/eu0CnJ2s5aLteeEDWqt1SjD9CBufGtTjNpCvSKR59Hl4quj2zwGF8P
+XHAxpnXOzdaxZtbi8h18ehtOxz23A2QJvKJYavIpTNwVPIvwnS2ryKrXnF8NjH+
s89xMc2ZE1JT+bjWA+DwcvjXPGmMBacijbfuKLrV77dYoML2dmPNvDJyuJpnvKQU
5FhfUjUILHmRYZJF5eT9f2KVt6cYzVlIUP9yxjbkrGoaAHGYijcASNZSQeRWvGER
S9T6TW7QO2TzetBT68xstHZBmcSEyKF+uQ9hoJjGAJJo6L1R2SQK8ILg3voyoF48
Hi+Ud5i9w7vF+UFVphVt+904nmruVzJ57oLlDts+q0jEODM6+YwQODgBR4JeXF6T
PJAXKpUBmYc12GzRSu6zlTDQIGJ0LewKtt/u1NLEDym3hWHs/2P2ISAO+/RLDv0U
klc3MndlgH1Ua9Gu6crLg9YrDxIguCooT1GQKnpOiic80n8VgMMViT3FsnMVGtmK
VQ9XVyotbZrni7ctWRywPpQIwZuKEs3J9A3wbCX/fwuKgTiB5XQvl7EHLypAbWUp
6X11aT86R3L9vOckHjywgLY=
=eji6
-----END PGP SIGNATURE-----

3
apparmor-v4.0.2.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0b847751b8c0e2344169ec2065cad6251063c5c5ff311953e194bbf25686d981
size 6987316

View File

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQJOBAABCgA4FiEEPs3Lpfs00lSWHMU/ZonmTj02ZLsFAmagRIsaHGFwcGFybW9y
QGxpc3RzLnVidW50dS5jb20ACgkQZonmTj02ZLtWbg//brM4s3laj5L+MnsiOeHr
x3V9lC3hM2N1IEMBLuEZLZ6pZg0WKDAyJ93DdBmVrX/xXIw6vPUvWRCW8rGv9JJr
e5KvCI8282gRqvldowc+GX92KuXVTWBafccqlxvfnjLPIjas1/Ft4oubsv5PK97F
ix4wlW6A+/CXNQ3vP2Dbpb/gVsCOwmSLqJUQz3g40PXUdmB6qHaw3XsIBQWUTX91
AIPQ6WA9OEp4kupqTgw0ih/8XsLVzb8xx8v5AzQILy1jEV4E7IIN01nN5dXrj+25
s0kZO1iEctNVgsU3Db7BJMJvAolps1R+c5I6grcS01FaOAwx1TuSacZaDkn+rqpn
mX62UOly3OHAV7WW1X5U/Jt0rqwekH1su1TlI66bqu7OATlfdceLXe0S79U8txEd
1T4iZZEPjflk5YjqNYN/C4nDgbNQ9wTDmnY4Q2+ExJKzv/ddD1ulEMiZAE/skNj2
ztdwB3RZ6aeck0iWuWq/EQsg4c68rnKxwmROzmMuAPtMF3SS1B3CKQDMVib/aJn7
DY+K4aXBMXrt0RTVa1n86/hDorWaJcB3XoVXGTaEAQhxzArVCF7/p3uVpoK0AM/D
VYCta1j6cFupVQAHRR2m2+Y3fOFiFRWY9TPE62TTNKERjLQpA2MujevkQ7UOGnuC
Q6BkrVpPQyVuhIXsP0GkH/c=
=fBvk
-----END PGP SIGNATURE-----

View File

@ -0,0 +1,166 @@
From aada708bc1c1787d190529aeafce66e3ce52fb7e Mon Sep 17 00:00:00 2001
From: Christian Boltz <apparmor@cboltz.de>
Date: Sun, 9 Jun 2024 21:51:01 +0200
Subject: [PATCH 1/2] MountRule: add support for quoted paths
While on it, make the output for failing tests more verbose for easier
debugging.
(cherry picked from commit 900f233101553182cffb29aab53e014d25138489,
test-mount.py adjusted for 4.0 branch)
---
utils/apparmor/rule/mount.py | 6 +++---
utils/test/test-mount.py | 4 +++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/utils/apparmor/rule/mount.py b/utils/apparmor/rule/mount.py
index b2d73a27b..992c29142 100644
--- a/utils/apparmor/rule/mount.py
+++ b/utils/apparmor/rule/mount.py
@@ -15,7 +15,7 @@ import re
from apparmor.common import AppArmorBug, AppArmorException
-from apparmor.regex import RE_PROFILE_MOUNT, strip_parenthesis
+from apparmor.regex import RE_PROFILE_MOUNT, strip_parenthesis, strip_quotes
from apparmor.rule import AARE
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, check_and_split_list
@@ -171,12 +171,12 @@ class MountRule(BaseRule):
options = cls.ALL
if operation == 'mount' and r['source_file'] is not None: # Umount cannot have a source
- source = r['source_file']
+ source = strip_quotes(r['source_file'])
else:
source = cls.ALL
if r['dest_file'] is not None:
- dest = r['dest_file']
+ dest = strip_quotes(r['dest_file'])
else:
dest = cls.ALL
diff --git a/utils/test/test-mount.py b/utils/test/test-mount.py
index cb1a89630..6dfe1ac85 100644
--- a/utils/test/test-mount.py
+++ b/utils/test/test-mount.py
@@ -42,7 +42,9 @@ class MountTestParse(AATest):
('mount fstype=(ext3, ext4) options=(ro),', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('mount @{mntpnt},', MountRule('mount', MountRule.ALL, MountRule.ALL, '@{mntpnt}', MountRule.ALL, False, False, False, '' )),
('mount /a,', MountRule('mount', MountRule.ALL, MountRule.ALL, '/a', MountRule.ALL, False, False, False, '' )),
+ ('mount "/a space",', MountRule('mount', MountRule.ALL, MountRule.ALL, '/a space', MountRule.ALL, False, False, False, '')),
('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, '/a', '/b', False, False, False, '' )),
+ ('mount fstype=(ext3, ext4) /a -> "/bar space",', MountRule('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, '/a', '/bar space', False, False, False, '')),
('mount fstype=(ext3, ext4) options=(ro, sync) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, '' )),
('mount fstype=(ext3, ext4) options=(ro, sync) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, ' #cmt')),
('mount fstype=({ext3,ext4}) options in (ro, sync) /a -> /b,', MountRule('mount', ('=', ['{ext3,ext4}']), ('in', ('ro', 'sync')), '/a', '/b', False, False, False, '' )),
@@ -66,7 +68,7 @@ class MountTestParse(AATest):
self.assertTrue(MountRule.match(rawrule))
obj = MountRule.create_instance(rawrule)
expected.raw_rule = rawrule.strip()
- self.assertTrue(obj.is_equal(expected, True))
+ self.assertTrue(obj.is_equal(expected, True), f'\n {rawrule} expected,\n {obj.get_clean()} returned by obj.get_clean()\n {expected.get_clean()} returned by expected.get_clean()')
def test_valid_mount_changing_propagation(self):
# Rules changing propagation type can either specify a source or a dest (these are equivalent for apparmor_parser in this specific case) but not both.
--
GitLab
From 98a0a2fee92b86155de258711c554f068ead8f6c Mon Sep 17 00:00:00 2001
From: Christian Boltz <apparmor@cboltz.de>
Date: Sun, 9 Jun 2024 23:03:13 +0200
Subject: [PATCH 2/2] MountRule: Add support for empty ("") source
This needs adding of an empty_ok flag in _aare_or_all().
Also add a few tests from boo#1226031 to utils and parser tests.
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1226031
(cherry picked from commit 1f33fc9b29c174698fdf0116a4a9f50680ec4fdb,
test-mount.py changes adjusted for 4.0 branch)
---
parser/tst/simple_tests/mount/ok_quoted_1.sd | 9 +++++++++
utils/apparmor/rule/__init__.py | 4 ++--
utils/apparmor/rule/mount.py | 4 ++--
utils/test/test-mount.py | 2 ++
4 files changed, 15 insertions(+), 4 deletions(-)
create mode 100644 parser/tst/simple_tests/mount/ok_quoted_1.sd
diff --git a/parser/tst/simple_tests/mount/ok_quoted_1.sd b/parser/tst/simple_tests/mount/ok_quoted_1.sd
new file mode 100644
index 000000000..c819caea3
--- /dev/null
+++ b/parser/tst/simple_tests/mount/ok_quoted_1.sd
@@ -0,0 +1,9 @@
+#
+#=Description basic mount rules with quoted paths
+#=EXRESULT PASS
+#
+/usr/bin/foo {
+ mount "" -> "/",
+ mount "" -> "/tmp/",
+ umount "/",
+}
diff --git a/utils/apparmor/rule/__init__.py b/utils/apparmor/rule/__init__.py
index ede7909ca..11e2f1f17 100644
--- a/utils/apparmor/rule/__init__.py
+++ b/utils/apparmor/rule/__init__.py
@@ -51,7 +51,7 @@ class BaseRule(metaclass=ABCMeta):
# Set only in the parse() class method
self.raw_rule = None
- def _aare_or_all(self, rulepart, partname, is_path, log_event):
+ def _aare_or_all(self, rulepart, partname, is_path, log_event, empty_ok=False):
"""checks rulepart and returns
- (AARE, False) if rulepart is a (non-empty) string
- (None, True) if rulepart is all_obj (typically *Rule.ALL)
@@ -67,7 +67,7 @@ class BaseRule(metaclass=ABCMeta):
if rulepart == self.ALL:
return None, True
elif isinstance(rulepart, str):
- if not rulepart.strip():
+ if not rulepart.strip() and not empty_ok:
raise AppArmorBug(
'Passed empty %(partname)s to %(classname)s: %(rulepart)s'
% {'partname': partname, 'classname': self.__class__.__name__, 'rulepart': str(rulepart)})
diff --git a/utils/apparmor/rule/mount.py b/utils/apparmor/rule/mount.py
index 992c29142..d20522971 100644
--- a/utils/apparmor/rule/mount.py
+++ b/utils/apparmor/rule/mount.py
@@ -66,7 +66,7 @@ mount_condition_pattern = rf'({fs_type_pattern})?\s*({option_pattern})?'
# - A path : /foo
# - A globbed Path : **
-glob_pattern = r'(\s*(?P<%s>(([/{]|\*\*)\S*|"([/{]|\*\*)[^"]*"|@{\S+}\S*|"@{\S+}[^"]*")|\w+))'
+glob_pattern = r'(\s*(?P<%s>(([/{]|\*\*)\S*|"([/{]|\*\*)[^"]*"|@{\S+}\S*|"@{\S+}[^"]*"|"")|\w+))'
source_fileglob_pattern = glob_pattern % 'source_file'
dest_fileglob_pattern = glob_pattern % 'dest_file'
@@ -114,7 +114,7 @@ class MountRule(BaseRule):
raise AppArmorException(_('Passed unknown options keyword to %s: %s') % (type(self).__name__, ' '.join(unknown_items)))
self.is_options_equal = options[0] if not self.all_options else None
- self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event)
+ self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event, empty_ok=True)
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
if not self.all_fstype and self.is_fstype_equal not in ('=', 'in'):
diff --git a/utils/test/test-mount.py b/utils/test/test-mount.py
index 6dfe1ac85..7af46a5d8 100644
--- a/utils/test/test-mount.py
+++ b/utils/test/test-mount.py
@@ -55,6 +55,8 @@ class MountTestParse(AATest):
MountRule('mount', MountRule.ALL, ('=', ('rw', 'rbind')), '{,/usr}/lib{,32,64,x32}/modules/',
'/tmp/snap.rootfs_*{,/usr}/lib/modules/',
False, False, False, '' )),
+ ('mount options=(runbindable, rw) -> /,', MountRule('mount', MountRule.ALL, ('=', ['runbindable', 'rw']), MountRule.ALL, '/', False, False, False, '')),
+ ('mount "" -> /,', MountRule('mount', MountRule.ALL, MountRule.ALL, '', '/', False, False, False, '')),
('umount,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('umount fstype=ext3,', MountRule('umount', ('=', ['ext3']), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('umount /a,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/a', False, False, False, '' )),
--
GitLab

31
plasmashell.diff Normal file
View File

@ -0,0 +1,31 @@
commit 64469afa2c65eb8a90a19d2b658a9559fb3964b0
Author: Christian Boltz <apparmor@cboltz.de>
Date: Tue Jun 4 21:14:50 2024 +0200
Add openSUSE path to plasmashell profile
While on it,
- add some comments explaining what the profile does
- adjust the rule with the Debian/Ubuntu path to work with Qt6
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1225961
diff --git a/profiles/apparmor.d/plasmashell b/profiles/apparmor.d/plasmashell
index d743ff7a3..51c50a689 100644
--- a/profiles/apparmor.d/plasmashell
+++ b/profiles/apparmor.d/plasmashell
@@ -17,8 +17,13 @@ profile plasmashell /usr/bin/plasmashell {
unix,
ptrace,
- /usr/lib/x86_64-linux-gnu/qt5/libexec/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
+ # allow executing QtWebEngineProcess with full permissions including userns (using profile stacking to avoid no_new_privs issues)
+ /usr/lib/x86_64-linux-gnu/qt[56]/libexec/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
+ /usr/libexec/qt[56]/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
+
+ # allow to execute all other programs under their own profile, or to run unconfined
/** pux,
+
/{,**} mrwlk,
profile QtWebEngineProcess {

48
sampa-rpcd-witness.diff Normal file
View File

@ -0,0 +1,48 @@
From https://gitlab.com/apparmor/apparmor/-/merge_requests/1256
(adjusted to currently packaged samba-rpcd profile)
From 94ccd111deac35d7deadb07e66d25e045633e221 Mon Sep 17 00:00:00 2001
From: Christian Boltz <apparmor@cboltz.de>
Date: Sat, 8 Jun 2024 22:46:53 +0200
Subject: [PATCH] samba-dcerpcd: allow to execute rpcd_witness
... and extend the samba-rpcd profile to also include rpcd_witness.
Patch by Noel Power <nopower@suse.com>
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1225811
---
profiles/apparmor.d/samba-dcerpcd | 2 +-
profiles/apparmor.d/samba-rpcd | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
Index: apparmor-v4.0.1/profiles/apparmor.d/samba-dcerpcd
===================================================================
--- apparmor-v4.0.1.orig/profiles/apparmor.d/samba-dcerpcd 2024-04-12 05:59:30.000000000 +0200
+++ apparmor-v4.0.1/profiles/apparmor.d/samba-dcerpcd 2024-06-25 21:49:49.017901846 +0200
@@ -21,7 +21,7 @@ profile samba-dcerpcd /usr/lib*/samba/{,
/usr/lib*/samba/{,samba/}samba-dcerpcd mr,
/usr/lib*/samba/ r,
- /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} Px -> samba-rpcd,
+ /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} Px -> samba-rpcd,
/usr/lib*/samba/{,samba/}rpcd_classic Px -> samba-rpcd-classic,
/usr/lib*/samba/{,samba/}rpcd_spoolss Px -> samba-rpcd-spoolss,
Index: apparmor-v4.0.1/profiles/apparmor.d/samba-rpcd
===================================================================
--- apparmor-v4.0.1.orig/profiles/apparmor.d/samba-rpcd 2024-04-12 05:59:30.000000000 +0200
+++ apparmor-v4.0.1/profiles/apparmor.d/samba-rpcd 2024-06-25 21:49:49.017901846 +0200
@@ -13,9 +13,9 @@ abi <abi/4.0>,
include <tunables/global>
-profile samba-rpcd /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} {
+profile samba-rpcd /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} {
include <abstractions/samba-rpcd>
- /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} mr,
+ /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} mr,
@{run}/samba/ncalrpc/np/winreg wr,

22
sddm-xauth.diff Normal file
View File

@ -0,0 +1,22 @@
commit 0c6e031c02fb18affd3bb7f15e269d9dd5c3317a
Author: Christian Boltz <apparmor@cboltz.de>
Date: Tue Jun 4 21:45:06 2024 +0200
abstractions/X: add another xauth path
This time it's /tmp/xauth_?????? r, which gets used by latest sddm.
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1223900
diff --git a/profiles/apparmor.d/abstractions/X b/profiles/apparmor.d/abstractions/X
index 6f0272d64..6df891185 100644
--- a/profiles/apparmor.d/abstractions/X
+++ b/profiles/apparmor.d/abstractions/X
@@ -28,6 +28,7 @@
owner @{run}/user/*/gdm/Xauthority r,
owner @{run}/user/*/X11/Xauthority r,
owner @{run}/user/*/xauth_* r,
+ owner /tmp/xauth_?????? r,
# the unix socket to use to connect to the display
/tmp/.X11-unix/* rw,

21
teardown-unconfined.diff Normal file
View File

@ -0,0 +1,21 @@
commit f497afbe1364b45540a6582870e5a76f1ada7a2b
Author: Christian Boltz <apparmor@cboltz.de>
Date: Tue May 28 21:13:47 2024 +0200
Fix aa-teardown for `unconfined` profiles
Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1225457
diff --git a/parser/rc.apparmor.functions b/parser/rc.apparmor.functions
index f66fea422..099ab67d3 100644
--- a/parser/rc.apparmor.functions
+++ b/parser/rc.apparmor.functions
@@ -253,7 +253,7 @@ remove_profiles() {
retval=0
# We filter child profiles as removing the parent will remove
# the children
- sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
+ sed -e "s/ (\(enforce\|complain\|unconfined\))$//" "$SFS_MOUNTPOINT/profiles" | \
LC_COLLATE=C sort | grep -v // | {
while read -r profile ; do
printf "%s" "$profile" > "$SFS_MOUNTPOINT/.remove"

30
test-aa-notify.diff Normal file
View File

@ -0,0 +1,30 @@
https://gitlab.com/apparmor/apparmor/-/merge_requests/1226
From 715cb711ba26d3ccff490f35f80721cf3678abb6 Mon Sep 17 00:00:00 2001
From: Christian Boltz <apparmor@cboltz.de>
Date: Sun, 5 May 2024 22:05:43 +0200
Subject: [PATCH] Don't rely on argparse saying "options:"
Some argparse versions (for example on openSUSE Leap 15.5) instead say
"optional arguments:"
Don't rely on the "options:" line to allow both wordings.
---
utils/test/test-aa-notify.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/utils/test/test-aa-notify.py b/utils/test/test-aa-notify.py
index 4f3e540e9..abffd0631 100644
--- a/utils/test/test-aa-notify.py
+++ b/utils/test/test-aa-notify.py
@@ -194,7 +194,6 @@ Display AppArmor notifications or messages for DENIED entries.
expected_output_2 = \
'''
-options:
-h, --help show this help message and exit
-p, --poll poll AppArmor logs and display notifications
--display DISPLAY set the DISPLAY environment variable (might be needed if
--
GitLab

View File

@ -0,0 +1,39 @@
From 553acd22324ed013d9f468aa8585518cf68b34f7 Mon Sep 17 00:00:00 2001
From: Christian Boltz <apparmor@cboltz.de>
Date: Sun, 21 Apr 2024 17:32:24 +0200
Subject: [PATCH] Fix redefinition of _
... which unsurprisingly broke using the translations.
This was a regression introduced in 4f51c93f9dc2516a32bfccc79b4dcf4985e61f47
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/387
---
utils/apparmor/tools.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/utils/apparmor/tools.py b/utils/apparmor/tools.py
index e8a99bbe6..f7d4a0d36 100644
--- a/utils/apparmor/tools.py
+++ b/utils/apparmor/tools.py
@@ -90,7 +90,7 @@ class aa_tools:
def get_next_for_modechange(self):
"""common code for mode/flags changes"""
- for (program, _, prof_filename) in self.get_next_to_profile():
+ for (program, ignored, prof_filename) in self.get_next_to_profile():
output_name = prof_filename if program is None else program
if not os.path.isfile(prof_filename) or is_skippable_file(prof_filename):
@@ -162,7 +162,7 @@ class aa_tools:
def cmd_autodep(self):
apparmor.loadincludes()
- for (program, _, prof_filename) in self.get_next_to_profile():
+ for (program, ignored, prof_filename) in self.get_next_to_profile():
if not program:
aaui.UI_Info(_('Please pass an application to generate a profile for, not a profile itself - skipping %s.') % prof_filename)
continue
--
GitLab

View File

@ -0,0 +1,182 @@
commit 1f4bba0448563b7d1fe4d86c230556ebf8d3805b
Author: Maxime Bélair <maxime.belair@canonical.com>
Date: Mon May 20 11:09:04 2024 +0200
Cherry-pick: MountRule: Aligning behavior with apparmor_parser
Mount Rules with options in { remount, [make-] { [r]unbindable, [r]shared, [r]private, and [r]slave }} do not support specifying a source. This commit aligns utils implementation to apparmor_parser's, which prohibits having a both source and a destination simultaneously, instad of just prohibiting source.
Therefore, both `mount options=(unbindable) /a,` and `mount options=(unbindable) -> /a,` are now supported (and equivalent for apparmor_parser). However, `mount options=(unbindable) /a -> /b,` is invalid.
For the same reason, specifying a fstype in these cases is also prohibited.
Similarly, we prohibit to specify a fstype for bind mount rules.
Fixes: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2065685
(cherry picked from commit 60acc4a4053ddb3718b9a2f5ceb1ef02fea3a226)
Signed-off-by: Maxime Bélair <maxime.belair@canonical.com>
diff --git a/utils/apparmor/rule/mount.py b/utils/apparmor/rule/mount.py
index abfa2b75e..b2d73a27b 100644
--- a/utils/apparmor/rule/mount.py
+++ b/utils/apparmor/rule/mount.py
@@ -25,15 +25,18 @@ _ = init_translation()
# TODO : Apparmor remount logs are displayed as mount (with remount flag). Profiles generated with aa-genprof are therefore mount rules. It could be interesting to make them remount rules.
-flags_keywords = [
- # keep in sync with parser/mount.cc mnt_opts_table!
- 'ro', 'r', 'read-only', 'rw', 'w', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'remount',
- 'mand', 'nomand', 'dirsync', 'symfollow', 'nosymfollow', 'atime', 'noatime', 'diratime', 'nodiratime', 'bind', 'B',
- 'move', 'M', 'rbind', 'R', 'verbose', 'silent', 'loud', 'acl', 'noacl', 'unbindable', 'make-unbindable', 'runbindable',
- 'make-runbindable', 'private', 'make-private', 'rprivate', 'make-rprivate', 'slave', 'make-slave', 'rslave', 'make-rslave',
- 'shared', 'make-shared', 'rshared', 'make-rshared', 'relatime', 'norelatime', 'iversion', 'noiversion', 'strictatime',
- 'nostrictatime', 'lazytime', 'nolazytime', 'user', 'nouser',
- '([A-Za-z0-9])',
+flags_bind_mount = {'B', 'bind', 'R', 'rbind'}
+flags_change_propagation = {
+ 'remount', 'unbindable', 'shared', 'private', 'slave', 'runbindable', 'rshared', 'rprivate', 'rslave',
+ 'make-unbindable', 'make-shared', 'make-private', 'make-slave', 'make-runbindable', 'make-rshared', 'make-rprivate',
+ 'make-rslave'
+}
+# keep in sync with parser/mount.cc mnt_opts_table!
+flags_keywords = list(flags_bind_mount) + list(flags_change_propagation) + [
+ 'ro', 'r', 'read-only', 'rw', 'w', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'mand',
+ 'nomand', 'dirsync', 'symfollow', 'nosymfollow', 'atime', 'noatime', 'diratime', 'nodiratime', 'move', 'M',
+ 'verbose', 'silent', 'loud', 'acl', 'noacl', 'relatime', 'norelatime', 'iversion', 'noiversion', 'strictatime',
+ 'nostrictatime', 'lazytime', 'nolazytime', 'user', 'nouser', '([A-Za-z0-9])',
]
join_valid_flags = '|'.join(flags_keywords)
@@ -112,6 +115,7 @@ class MountRule(BaseRule):
self.is_options_equal = options[0] if not self.all_options else None
self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event)
+ self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
if not self.all_fstype and self.is_fstype_equal not in ('=', 'in'):
raise AppArmorBug(f'Invalid is_fstype_equal : {self.is_fstype_equal}')
@@ -120,11 +124,14 @@ class MountRule(BaseRule):
if self.operation != 'mount' and not self.all_source:
raise AppArmorException(f'Operation {self.operation} cannot have a source')
- flags_forbidden_with_source = {'remount', 'unbindable', 'shared', 'private', 'slave', 'runbindable', 'rshared', 'rprivate', 'rslave'}
- if self.operation == 'mount' and not self.all_source and not self.all_options and flags_forbidden_with_source & self.options != set():
- raise AppArmorException(f'Operation {flags_forbidden_with_source & self.options} cannot have a source. Source = {self.source}')
+ if self.operation == 'mount' and not self.all_options and flags_change_propagation & self.options != set():
+ if not (self.all_source or self.all_dest):
+ raise AppArmorException(f'Operation {flags_change_propagation & self.options} cannot specify a source. Source = {self.source}')
+ elif not self.all_fstype:
+ raise AppArmorException(f'Operation {flags_change_propagation & self.options} cannot specify a fstype. Fstype = {self.fstype}')
- self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
+ if self.operation == 'mount' and not self.all_options and flags_bind_mount & self.options != set() and not self.all_fstype:
+ raise AppArmorException(f'Bind mount rules cannot specify a fstype. Fstype = {self.fstype}')
self.can_glob = not self.all_source and not self.all_dest and not self.all_options
diff --git a/utils/test/test-mount.py b/utils/test/test-mount.py
index 7f88ff7db..cb1a89630 100644
--- a/utils/test/test-mount.py
+++ b/utils/test/test-mount.py
@@ -43,12 +43,12 @@ class MountTestParse(AATest):
('mount @{mntpnt},', MountRule('mount', MountRule.ALL, MountRule.ALL, '@{mntpnt}', MountRule.ALL, False, False, False, '' )),
('mount /a,', MountRule('mount', MountRule.ALL, MountRule.ALL, '/a', MountRule.ALL, False, False, False, '' )),
('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, '/a', '/b', False, False, False, '' )),
- ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
- ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
- ('mount fstype=({ext3,ext4}) options in (ro, rbind) /a -> /b,', MountRule('mount', ('=', ['{ext3,ext4}']), ('in', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
- ('mount fstype in (ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
- ('mount fstype in (ext3, ext4) option in (ro, rbind) /a, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('in', ('ro', 'rbind')), '/a', MountRule.ALL, False, False, False, ' #cmt')),
- ('mount fstype=(ext3, ext4) option=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype=(ext3, ext4) options=(ro, sync) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, '' )),
+ ('mount fstype=(ext3, ext4) options=(ro, sync) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype=({ext3,ext4}) options in (ro, sync) /a -> /b,', MountRule('mount', ('=', ['{ext3,ext4}']), ('in', ('ro', 'sync')), '/a', '/b', False, False, False, '' )),
+ ('mount fstype in (ext3, ext4) options=(ro, sync) /a -> /b, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype in (ext3, ext4) option in (ro, sync) /a, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('in', ('ro', 'sync')), '/a', MountRule.ALL, False, False, False, ' #cmt')),
+ ('mount fstype=(ext3, ext4) option=(ro, sync) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'sync')), '/a', '/b', False, False, False, ' #cmt')),
('mount options=(rw, rbind) {,/usr}/lib{,32,64,x32}/modules/ -> /tmp/snap.rootfs_*{,/usr}/lib/modules/,',
MountRule('mount', MountRule.ALL, ('=', ('rw', 'rbind')), '{,/usr}/lib{,32,64,x32}/modules/',
'/tmp/snap.rootfs_*{,/usr}/lib/modules/',
@@ -68,6 +68,17 @@ class MountTestParse(AATest):
expected.raw_rule = rawrule.strip()
self.assertTrue(obj.is_equal(expected, True))
+ def test_valid_mount_changing_propagation(self):
+ # Rules changing propagation type can either specify a source or a dest (these are equivalent for apparmor_parser in this specific case) but not both.
+ MountRule('mount', MountRule.ALL, ('=', ('runbindable')), '/foo', MountRule.ALL)
+ MountRule('mount', MountRule.ALL, ('=', ('runbindable')), MountRule.ALL, '/foo')
+
+ def test_valid_bind_mount(self):
+ # Fstype must remain empty in bind rules
+ MountRule('mount', MountRule.ALL, ('=', ('bind')), '/foo', MountRule.ALL)
+ MountRule('mount', MountRule.ALL, ('=', ('bind')), MountRule.ALL, '/bar')
+ MountRule('mount', MountRule.ALL, ('=', ('bind')), '/foo', '/bar')
+
class MountTestParseInvalid(AATest):
tests = (
@@ -143,6 +154,20 @@ class MountTestParseInvalid(AATest):
with self.assertRaises(AppArmorException):
MountRule('remount', MountRule.ALL, MountRule.ALL, '/foo', MountRule.ALL)
+ def test_invalid_mount_changing_propagation(self):
+ # Rules changing propagation type can either specify a source or a dest (these are equivalent for apparmor_parser in this specific case) but not both.
+ with self.assertRaises(AppArmorException):
+ MountRule('mount', MountRule.ALL, ('=', ('runbindable')), '/foo', '/bar')
+
+ # Rules changing propagation type cannot specify a fstype.
+ with self.assertRaises(AppArmorException):
+ MountRule('mount', ('=', ('ext4')), ('=', ('runbindable')), MountRule.ALL, '/foo')
+
+ def test_invalid_bind_mount(self):
+ # Bind mount rules cannot specify a fstype.
+ with self.assertRaises(AppArmorException):
+ MountRule('mount', ('=', ('ext4')), ('=', ('bind')), MountRule.ALL, '/foo')
+
class MountTestGlob(AATest):
def test_glob(self):
diff --git a/utils/test/test-parser-simple-tests.py b/utils/test/test-parser-simple-tests.py
index 451af7d22..60a738aed 100644
--- a/utils/test/test-parser-simple-tests.py
+++ b/utils/test/test-parser-simple-tests.py
@@ -85,16 +85,6 @@ exception_not_raised = (
'mount/bad_1.sd',
'mount/bad_2.sd',
- # not checked/detected: "make-*" mount opt and an invalid src
- 'mount/bad_opt_17.sd',
- 'mount/bad_opt_18.sd',
- 'mount/bad_opt_19.sd',
- 'mount/bad_opt_20.sd',
- 'mount/bad_opt_21.sd',
- 'mount/bad_opt_22.sd',
- 'mount/bad_opt_23.sd',
- 'mount/bad_opt_24.sd',
-
'profile/flags/flags_bad10.sd',
'profile/flags/flags_bad11.sd',
'profile/flags/flags_bad12.sd',
@@ -324,19 +314,6 @@ unknown_line = (
'bare_include_tests/ok_85.sd',
'bare_include_tests/ok_86.sd',
- # Mount with flags in {remount, [r]unbindable, [r]shared, [r]private, [r]slave} does not support a source
- 'mount/ok_opt_68.sd',
- 'mount/ok_opt_69.sd',
- 'mount/ok_opt_70.sd',
- 'mount/ok_opt_71.sd',
- 'mount/ok_opt_72.sd',
- 'mount/ok_opt_73.sd',
- 'mount/ok_opt_74.sd',
- 'mount/ok_opt_75.sd',
-
- # options=slave with /** src (first rule in the test causes exception)
- 'mount/ok_opt_84.sd',
-
# According to spec mount should be in the form fstype=... options=... and NOT in the form options=... fstype=...
'mount/ok_opt_combo_3.sd',
'mount/ok_opt_combo_2.sd',

View File

@ -0,0 +1,366 @@
commit eee50538da9a240bc151f26c6cff309808d33590
Author: Georgia Garcia <georgia.garcia@canonical.com>
Date: Wed May 8 12:58:42 2024 +0000
Merge MountRule: Relaxing constraints on fstype and completing AARE support
- Before this commit, fstype had to match a known fs. However, having and maintaining the exhaustive list of fstypes proved challenging (see !1195 and !1176). Therefore, we add support for any filesystem name.
- Completing AARE support for fstype (brace expressions like ext{3,4} are now supported).
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1198
Approved-by: Christian Boltz <apparmor@cboltz.de>
Merged-by: Christian Boltz <apparmor@cboltz.de>
(cherry picked from commit baa8b67248f3467cde40683600d7a945b05f9a3b)
dad5ee28 MountRule: Relaxing constraints on fstype and completing AARE support
Co-authored-by: Christian Boltz <apparmor@cboltz.de>
diff --git a/utils/apparmor/rule/mount.py b/utils/apparmor/rule/mount.py
index f62c08e4b..abfa2b75e 100644
--- a/utils/apparmor/rule/mount.py
+++ b/utils/apparmor/rule/mount.py
@@ -23,19 +23,7 @@ from apparmor.translations import init_translation
_ = init_translation()
-# TODO :
-# - match correctly AARE on every field
-# - Find the actual list of supported filesystems. This one comes from /proc/filesystems. We also blindly accept fuse.*
-# - Support path that begin by { (e.g. {,/usr}/lib/...) This syntax is not a valid AARE but is used by usr.lib.snapd.snap-confine.real in Ubuntu and will currently raise an error in genprof if these lines are not modified.
-# - Apparmor remount logs are displayed as mount (with remount flag). Profiles generated with aa-genprof are therefore mount rules. It could be interesting to make them remount rules.
-
-valid_fs = [
- 'sysfs', 'tmpfs', 'bdevfs', 'procfs', 'cgroup', 'cgroup2', 'cpuset', 'devtmpfs', 'configfs', 'debugfs', 'tracefs',
- 'securityfs', 'sockfs', 'bpf', 'npipefs', 'ramfs', 'hugetlbfs', 'devpts', 'ext3', 'ext2', 'ext4', 'squashfs',
- 'vfat', 'ecryptfs', 'fuseblk', 'fuse', 'fusectl', 'efivarfs', 'mqueue', 'store', 'autofs', 'binfmt_misc', 'overlay',
- 'none', 'bdev', 'proc', 'pipefs', 'pstore', 'btrfs', 'xfs', '9p', 'resctrl', 'zfs', 'iso9660', 'udf', 'ntfs3',
- 'nfs', 'cifs', 'overlayfs', 'aufs', 'rpc_pipefs', 'msdos', 'nfs4',
-]
+# TODO : Apparmor remount logs are displayed as mount (with remount flag). Profiles generated with aa-genprof are therefore mount rules. It could be interesting to make them remount rules.
flags_keywords = [
# keep in sync with parser/mount.cc mnt_opts_table!
@@ -48,7 +36,6 @@ flags_keywords = [
'([A-Za-z0-9])',
]
join_valid_flags = '|'.join(flags_keywords)
-join_valid_fs = '|'.join(valid_fs)
sep = r'\s*[\s,]\s*'
@@ -106,27 +93,18 @@ class MountRule(BaseRule):
self.operation = operation
- self.fstype, self.all_fstype, unknown_items = check_and_split_list(fstype[1] if fstype != self.ALL else fstype, valid_fs, self.ALL, type(self).__name__, 'fstype')
-
- if unknown_items:
- for it in unknown_items:
-
- # Several filesystems use fuse internally and are referred as fuse.<software_name> (e.g. fuse.jmtpfs, fuse.s3fs, fuse.obexfs).
- # Since this list seems to evolve too fast for a fixed list to work in practice, we just accept fuse.*
- # See https://github.com/libfuse/libfuse/wiki/Filesystems and, https://doc.ubuntu-fr.org/fuse
- if it.startswith('fuse.') and len(it) > 5:
- continue
-
- it = AARE(it, is_path=False)
- found = False
- for fs in valid_fs:
- if self._is_covered_aare(it, self.all_fstype, AARE(fs, False), self.all_fstype, 'fstype'):
- found = True
- break
- if not found:
- raise AppArmorException(_('Passed unknown fstype keyword to %s: %s') % (type(self).__name__, ' '.join(unknown_items)))
-
- self.is_fstype_equal = fstype[0] if not self.all_fstype else None
+ if fstype == self.ALL or fstype[1] == self.ALL:
+ self.all_fstype = True
+ self.fstype = None
+ self.is_fstype_equal = None
+ else:
+ self.all_fstype = False
+ for it in fstype[1]:
+ l, unused = parse_aare(it, 0, 'fstype')
+ if l != len(it):
+ raise AppArmorException(f'Invalid aare : {it}')
+ self.fstype = fstype[1]
+ self.is_fstype_equal = fstype[0]
self.options, self.all_options, unknown_items = check_and_split_list(options[1] if options != self.ALL else options, flags_keywords, self.ALL, type(self).__name__, 'options')
if unknown_items:
@@ -173,7 +151,7 @@ class MountRule(BaseRule):
if r['fstype'] is not None:
is_fstype_equal = r['fstype_equals_or_in']
- fstype = strip_parenthesis(r['fstype']).replace(',', ' ').split()
+ fstype = parse_aare_list(strip_parenthesis(r['fstype']), 'fstype')
else:
is_fstype_equal = None
fstype = cls.ALL
@@ -316,6 +294,38 @@ class MountRuleset(BaseRuleset):
'''Class to handle and store a collection of Mount rules'''
+
+def parse_aare(s, offset, param):
+ parsed = ''
+ brace_count = 0
+ for i, c in enumerate(s[offset:], start=offset):
+ if c in [' ', ',', '\t'] and brace_count == 0:
+ break
+ parsed += c
+ if c == '{':
+ brace_count += 1
+ elif c == '}':
+ brace_count -= 1
+ if brace_count < 0:
+ raise AppArmorException(f"Unmatched closing brace in {param}: {s[offset:]}")
+ offset = i
+
+ if brace_count != 0:
+ raise AppArmorException(f"Unmatched opening brace in {param}: {s[offset:]}")
+
+ return offset + 1, parsed
+
+
+def parse_aare_list(s, param):
+ res = []
+ offset = 0
+ while offset <= len(s):
+ offset, part = parse_aare(s, offset, param)
+ if part.translate(' ,\t') != '':
+ res.append(part)
+ return res
+
+
def wrap_in_with_spaces(value):
''' wrap 'in' keyword in spaces, and leave everything else unchanged '''
diff --git a/utils/test/test-mount.py b/utils/test/test-mount.py
index e37c287c7..7f88ff7db 100644
--- a/utils/test/test-mount.py
+++ b/utils/test/test-mount.py
@@ -20,7 +20,7 @@ from common_test import AATest, setup_all_loops
from apparmor.common import AppArmorException, AppArmorBug
from apparmor.translations import init_translation
-from apparmor.rule.mount import MountRule, valid_fs
+from apparmor.rule.mount import MountRule
_ = init_translation()
@@ -31,34 +31,34 @@ class MountTestParse(AATest):
# Rule Operation Filesystem Options Source Destination Audit Deny Allow Comment
('mount -> **,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '**', False, False, False, '' )),
('mount options=(rw, shared) -> **,', MountRule('mount', MountRule.ALL, ('=', ('rw', 'shared')), MountRule.ALL, '**', False, False, False, '' )),
- ('mount fstype=bpf options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('bpf')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
- ('mount fstype=fuse.obex* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.obex*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
- ('mount fstype=fuse.* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
- ('mount fstype=bpf options=(rw) random_label -> /sys/fs/bpf/,', MountRule('mount', ('=', ("bpf")), ('=', ('rw')), 'random_label', '/sys/fs/bpf/', False, False, False, '' )),
+ ('mount fstype=bpf options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ['bpf']), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
+ ('mount fstype=fuse.obex* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ['fuse.obex*']), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
+ ('mount fstype=fuse.* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ['fuse.*']), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
+ ('mount fstype=bpf options=(rw) random_label -> /sys/fs/bpf/,', MountRule('mount', ('=', ['bpf']), ('=', ('rw')), 'random_label', '/sys/fs/bpf/', False, False, False, '' )),
('mount,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
- ('mount fstype=(ext3, ext4),', MountRule('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
+ ('mount fstype=(ext3, ext4),', MountRule('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('mount bpf,', MountRule('mount', MountRule.ALL, MountRule.ALL, 'bpf', MountRule.ALL, False, False, False, '' )),
('mount none,', MountRule('mount', MountRule.ALL, MountRule.ALL, 'none', MountRule.ALL, False, False, False, '' )),
- ('mount fstype=(ext3, ext4) options=(ro),', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), MountRule.ALL, MountRule.ALL, False, False, False, '' )),
+ ('mount fstype=(ext3, ext4) options=(ro),', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('mount @{mntpnt},', MountRule('mount', MountRule.ALL, MountRule.ALL, '@{mntpnt}', MountRule.ALL, False, False, False, '' )),
('mount /a,', MountRule('mount', MountRule.ALL, MountRule.ALL, '/a', MountRule.ALL, False, False, False, '' )),
- ('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, '/a', '/b', False, False, False, '' )),
- ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
- ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
- ('mount fstype=(ext3, ext4) options in (ro, rbind) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), ('in', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
- ('mount fstype in (ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('in', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
- ('mount fstype in (ext3, ext4) option in (ro, rbind) /a, #cmt', MountRule('mount', ('in', ('ext3', 'ext4')), ('in', ('ro', 'rbind')), '/a', MountRule.ALL, False, False, False, ' #cmt')),
- ('mount fstype=(ext3, ext4) option=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, '/a', '/b', False, False, False, '' )),
+ ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b,', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
+ ('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype=({ext3,ext4}) options in (ro, rbind) /a -> /b,', MountRule('mount', ('=', ['{ext3,ext4}']), ('in', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
+ ('mount fstype in (ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
+ ('mount fstype in (ext3, ext4) option in (ro, rbind) /a, #cmt', MountRule('mount', ('in', ['ext3', 'ext4']), ('in', ('ro', 'rbind')), '/a', MountRule.ALL, False, False, False, ' #cmt')),
+ ('mount fstype=(ext3, ext4) option=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
('mount options=(rw, rbind) {,/usr}/lib{,32,64,x32}/modules/ -> /tmp/snap.rootfs_*{,/usr}/lib/modules/,',
MountRule('mount', MountRule.ALL, ('=', ('rw', 'rbind')), '{,/usr}/lib{,32,64,x32}/modules/',
'/tmp/snap.rootfs_*{,/usr}/lib/modules/',
False, False, False, '' )),
('umount,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
- ('umount fstype=ext3,', MountRule('umount', ('=', ('ext3')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
+ ('umount fstype=ext3,', MountRule('umount', ('=', ['ext3']), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('umount /a,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/a', False, False, False, '' )),
('remount,', MountRule('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
- ('remount fstype=ext4,', MountRule('remount', ('=', ('ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
+ ('remount fstype=ext4,', MountRule('remount', ('=', ['ext4']), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
('remount /b,', MountRule('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/b', False, False, False, '' )),
)
@@ -72,7 +72,6 @@ class MountTestParse(AATest):
class MountTestParseInvalid(AATest):
tests = (
('mount fstype=,', AppArmorException),
- ('mount fstype=(foo),', AppArmorException),
('mount fstype=(),', AppArmorException),
('mount options=(),', AppArmorException),
('mount option=(invalid),', AppArmorException),
@@ -90,7 +89,7 @@ class MountTestParseInvalid(AATest):
def test_diff_non_mountrule(self):
exp = namedtuple('exp', ('audit', 'deny'))
- obj = MountRule('mount', ('=', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
+ obj = MountRule('mount', ('=', ['ext4']), MountRule.ALL, MountRule.ALL, MountRule.ALL)
with self.assertRaises(AppArmorBug):
obj.is_equal(exp(False, False), False)
@@ -98,9 +97,25 @@ class MountTestParseInvalid(AATest):
with self.assertRaises(AppArmorBug):
MountRule('mount', ('ext3', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
- def test_diff_invalid_fstype_keyword(self):
- with self.assertRaises(AppArmorException):
- MountRule('mount', ('=', 'invalidfs'), MountRule.ALL, MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
+ def test_diff_invalid_fstype_aare(self):
+ tests = [
+ 'mount fstype=({unclosed_regex),',
+ 'mount fstype=({closed}twice}),',
+ ]
+
+ for t in tests:
+ with self.assertRaises(AppArmorException):
+ MountRule.create_instance(t)
+
+ def test_diff_invalid_fstype_aare_2(self):
+ fslists = [
+ ['invalid_{_regex'],
+ ['ext4', 'invalid_}_regex'],
+ ['ext4', '{invalid} {regex}']
+ ]
+ for fslist in fslists:
+ with self.assertRaises(AppArmorException):
+ MountRule('mount', ('=', fslist), MountRule.ALL, MountRule.ALL, MountRule.ALL)
def test_diff_invalid_options_equals_or_in(self):
with self.assertRaises(AppArmorBug):
@@ -111,7 +126,7 @@ class MountTestParseInvalid(AATest):
MountRule('mount', MountRule.ALL, ('=', 'invalid'), MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
def test_diff_fstype(self):
- obj1 = MountRule('mount', ('=', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
+ obj1 = MountRule('mount', ('=', ['ext4']), MountRule.ALL, MountRule.ALL, MountRule.ALL)
obj2 = MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL)
self.assertFalse(obj1.is_equal(obj2, False))
@@ -129,14 +144,6 @@ class MountTestParseInvalid(AATest):
MountRule('remount', MountRule.ALL, MountRule.ALL, '/foo', MountRule.ALL)
-class MountTestFilesystems(AATest):
- def test_fs(self):
- with open('/proc/filesystems') as f:
- for line in f:
- fs_name = line.split()[-1]
- self.assertTrue(fs_name in valid_fs, '/proc/filesystems contains %s which is not listed in MountRule valid_fs' % fs_name)
-
-
class MountTestGlob(AATest):
def test_glob(self):
globList = [(
@@ -199,49 +206,58 @@ class MountIsCoveredTest(AATest):
def test_is_covered(self):
obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/b*')
tests = [
- ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b', '/bar'),
- ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/bar', '/b')
+ ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), '/foo/b', '/bar'),
+ ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), '/foo/bar', '/b')
]
for test in tests:
self.assertTrue(obj.is_covered(MountRule(*test)))
self.assertFalse(obj.is_equal(MountRule(*test)))
def test_is_covered_fs_source(self):
- obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
- self.assertTrue(obj.is_covered(MountRule('mount', ('=', ('ext3')), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
- self.assertFalse(obj.is_equal(MountRule('mount', ('=', ('ext3')), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
+ obj = MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ self.assertTrue(obj.is_covered(MountRule('mount', ('=', ['ext3']), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
+ self.assertFalse(obj.is_equal(MountRule('mount', ('=', ['ext3']), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
- def test_is_covered_regex(self):
- obj = MountRule('mount', ('=', ('sys*', 'fuse.*')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ def test_is_covered_aare_1(self):
+ obj = MountRule('mount', ('=', ['sys*', 'fuse.*']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
tests = [
- ('mount', ('=', ('sysfs', 'fuse.s3fs')), ('=', ('ro')), 'tmpfs', MountRule.ALL),
- ('mount', ('=', ('sysfs', 'fuse.jmtpfs', 'fuse.s3fs', 'fuse.obexfs', 'fuse.obexautofs', 'fuse.fuseiso')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ ('mount', ('=', ['sysfs', 'fuse.s3fs']), ('=', ('ro')), 'tmpfs', MountRule.ALL),
+ ('mount', ('=', ['sysfs', 'fuse.jmtpfs', 'fuse.s3fs', 'fuse.obexfs', 'fuse.obexautofs', 'fuse.fuseiso']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ ]
+ for test in tests:
+ self.assertTrue(obj.is_covered(MountRule(*test)))
+ self.assertFalse(obj.is_equal(MountRule(*test)))
+ def test_is_covered_aare_2(self):
+ obj = MountRule('mount', ('=', ['ext{3,4}', '{cgroup*,fuse.*}']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ tests = [
+ ('mount', ('=', ['ext3']), ('=', ('ro')), 'tmpfs', MountRule.ALL),
+ ('mount', ('=', ['ext3', 'ext4', 'cgroup', 'cgroup2', 'fuse.jmtpfs', 'fuse.s3fs', 'fuse.obexfs', 'fuse.obexautofs', 'fuse.fuseiso']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
]
for test in tests:
self.assertTrue(obj.is_covered(MountRule(*test)))
self.assertFalse(obj.is_equal(MountRule(*test)))
def test_is_notcovered(self):
- obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/b*')
+ obj = MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), '/foo/b*', '/b*')
tests = [
- ('mount', ('in', ('ext3', 'ext4')), ('=', ('ro')), '/foo/bar', '/bar' ),
- ('mount', ('=', ('procfs', 'ext4')), ('=', ('ro')), '/foo/bar', '/bar' ),
- ('mount', ('=', ('ext3')), ('=', ('rw')), '/foo/bar', '/bar' ),
- ('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, '/foo/b*', '/bar' ),
+ ('mount', ('in', ['ext3', 'ext4']), ('=', ('ro')), '/foo/bar', '/bar' ),
+ ('mount', ('=', ['procfs', 'ext4']), ('=', ('ro')), '/foo/bar', '/bar' ),
+ ('mount', ('=', ['ext3']), ('=', ('rw')), '/foo/bar', '/bar' ),
+ ('mount', ('=', ['ext3', 'ext4']), MountRule.ALL, '/foo/b*', '/bar' ),
('mount', MountRule.ALL, ('=', ('ro')), '/foo/b*', '/bar' ),
- ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/invalid/bar', '/bar' ),
+ ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), '/invalid/bar', '/bar' ),
('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/bar' ),
('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/bar' ),
- ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', '/bar' ),
- ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/invalid'),
+ ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), 'tmpfs', '/bar' ),
+ ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), '/foo/b*', '/invalid'),
]
for test in tests:
self.assertFalse(obj.is_covered(MountRule(*test)))
self.assertFalse(obj.is_equal(MountRule(*test)))
def test_is_not_covered_fs_source(self):
- obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
- test = ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'procfs', MountRule.ALL)
+ obj = MountRule('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), 'tmpfs', MountRule.ALL)
+ test = ('mount', ('=', ['ext3', 'ext4']), ('=', ('ro')), 'procfs', MountRule.ALL)
self.assertFalse(obj.is_covered(MountRule(*test)))
self.assertFalse(obj.is_equal(MountRule(*test)))
diff --git a/utils/test/test-parser-simple-tests.py b/utils/test/test-parser-simple-tests.py
index 40f61ef85..451af7d22 100644
--- a/utils/test/test-parser-simple-tests.py
+++ b/utils/test/test-parser-simple-tests.py
@@ -324,9 +324,6 @@ unknown_line = (
'bare_include_tests/ok_85.sd',
'bare_include_tests/ok_86.sd',
- # mount with fstype using AARE
- 'mount/ok_12.sd',
-
# Mount with flags in {remount, [r]unbindable, [r]shared, [r]private, [r]slave} does not support a source
'mount/ok_opt_68.sd',
'mount/ok_opt_69.sd',