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 7e657a915..14919dccc 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 37e41c27b..0880b3367 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 b3e415fb7..8ec57148a 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/', # noqa: E127 '/tmp/snap.rootfs_*{,/usr}/lib/modules/', # noqa: E127 False, False, False, '')), # noqa: E127 + ('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, '')),