2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00

Merge Fix parsing of mount options to honor full words

Parsing mount options (also) accepted partial matches as long as the
option started with the right characters. For example, 'options=syncfoo'
was parsed as 'sync'. This is also the reason why the list of mount
options was re-ordered so that 'r' and 'w' came last to give longer
options a chance to match (otherwise, 'rw' would be interpreted as 'r').

Fix parsing by adding a lookahead match so that the regex enforces that
the mount option is followed by whitespace, or is at the end of
rule_details.

Note that this issue only affected the options=foo syntax.
options=(foo) worked correctly even without this fix.


Now that this is fixed, move 'r' and 'w' back to their original position
in the list of mount options.

Also add a test where a mount rule ends with 'options=rw,' to ensure
that the '$' lookahead works.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1712
Approved-by: Georgia Garcia <georgia.garcia@canonical.com>
Merged-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
Georgia Garcia 2025-06-05 09:33:06 -03:00
commit 9fceca5b88
2 changed files with 4 additions and 4 deletions

View File

@ -32,12 +32,11 @@ flags_change_propagation = {
'make-rslave'
}
# keep in sync with parser/mount.cc mnt_opts_table!
# ordering is relevant here due to re.finditer - if r is present in the list before rw, then options will match r, not rw
flags_keywords = list(flags_bind_mount) + list(flags_change_propagation) + [
'ro', 'read-only', 'rw', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'mand',
'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', 'r', 'w',
'nostrictatime', 'lazytime', 'nolazytime', 'user', 'nouser',
'[A-Za-z0-9-]+', # as long as the parser uses a hardcoded options list, this only helps to print a better error message on unknown mount options
]
join_valid_flags = '|'.join(flags_keywords)
@ -54,7 +53,7 @@ fs_type_pattern = r'\b(?P<fstype_or_vfstype>fstype|vfstype)\b\s*(?P<fstype_equal
option_pattern = r'\s*(\boption(s?)\b\s*(?P<options_equals_or_in>=|in)\s*'\
r'(?P<options>\(\s*(' + join_valid_flags + r')(' + sep + r'(' + join_valid_flags + r'))*\s*\)|' \
r'(\s*' + join_valid_flags + r')'\
r'(\s*' + join_valid_flags + r')(?=(\s|$))'\
r'))'
# allow any order of fstype and options

View File

@ -31,6 +31,7 @@ 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 options=rw,', MountRule('mount', MountRule.ALL, ('=', ('rw')), MountRule.ALL, 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, '')),