diff options
author | Luis Hector Chavez <lhchavez@google.com> | 2019-03-27 11:14:05 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-03-27 11:14:05 -0700 |
commit | de90bdab74bef72596fb9f9289c28cf0e4f04c2d (patch) | |
tree | 1196868f01114fc16578b4dd66d5601489330ea2 | |
parent | 63fd0b84fbe504a15305aec0445aab1ba47d1d12 (diff) | |
parent | cc10dc27e924859a59292b4d887d5edc2d796ee5 (diff) | |
download | minijail-de90bdab74bef72596fb9f9289c28cf0e4f04c2d.tar.gz |
tools/compile_seccomp_policy: Add support for syscall groups am: 524da3bc42
am: cc10dc27e9
Change-Id: I147b61576b3058f67d688f7a636628d251dd1c86
-rw-r--r-- | tools/arch.py | 8 | ||||
-rw-r--r-- | tools/parser.py | 23 | ||||
-rwxr-xr-x | tools/parser_unittest.py | 23 | ||||
-rw-r--r-- | tools/testdata/arch_64.json | 14 |
4 files changed, 62 insertions, 6 deletions
diff --git a/tools/arch.py b/tools/arch.py index 6f2dfb2..ac2f32b 100644 --- a/tools/arch.py +++ b/tools/arch.py @@ -21,9 +21,10 @@ import json class Arch( - collections.namedtuple( - 'Arch', - ['arch_nr', 'arch_name', 'bits', 'syscalls', 'constants'])): + collections.namedtuple('Arch', [ + 'arch_nr', 'arch_name', 'bits', 'syscalls', 'constants', + 'syscall_groups' + ])): """Holds architecture-specific information.""" def truncate_word(self, value): @@ -51,4 +52,5 @@ class Arch( bits=constants['bits'], syscalls=constants['syscalls'], constants=constants['constants'], + syscall_groups=constants.get('syscall_groups', {}), ) diff --git a/tools/parser.py b/tools/parser.py index 41d2f52..65297f9 100644 --- a/tools/parser.py +++ b/tools/parser.py @@ -57,7 +57,7 @@ _TOKEN_SPECIFICATION = ( ('ARGUMENT', r'arg[0-9]+'), ('RETURN', r'return'), ('ACTION', r'allow|kill-process|kill-thread|kill|trap|trace|log'), - ('IDENTIFIER', r'[a-zA-Z_][a-zA-Z_0-9@]*'), + ('IDENTIFIER', r'[a-zA-Z_][a-zA-Z_0-9-@]*'), ) _TOKEN_RE = re.compile('|'.join( r'(?P<%s>%s)' % pair for pair in _TOKEN_SPECIFICATION)) @@ -481,7 +481,7 @@ class PolicyParser: return metadata # syscall-descriptor = syscall-name , [ metadata ] - # | libc-function , [ metadata ] + # | syscall-group-name , [ metadata ] # ; def _parse_syscall_descriptor(self, tokens): if not tokens: @@ -490,11 +490,28 @@ class PolicyParser: if syscall_descriptor.type != 'IDENTIFIER': self._parser_state.error( 'invalid syscall descriptor', token=syscall_descriptor) - # TODO(lhchavez): Support libc function names. if tokens and tokens[0].type == 'LBRACKET': metadata = self._parse_metadata(tokens) if 'arch' in metadata and self._arch.arch_name not in metadata['arch']: return () + if '@' in syscall_descriptor.value: + # This is a syscall group. + subtokens = syscall_descriptor.value.split('@') + if len(subtokens) != 2: + self._parser_state.error( + 'invalid syscall group name', token=syscall_descriptor) + syscall_group_name, syscall_namespace_name = subtokens + if syscall_namespace_name not in self._arch.syscall_groups: + self._parser_state.error( + 'nonexistent syscall group namespace', + token=syscall_descriptor) + syscall_namespace = self._arch.syscall_groups[ + syscall_namespace_name] + if syscall_group_name not in syscall_namespace: + self._parser_state.error( + 'nonexistent syscall group', token=syscall_descriptor) + return (Syscall(name, self._arch.syscalls[name]) + for name in syscall_namespace[syscall_group_name]) if syscall_descriptor.value not in self._arch.syscalls: self._parser_state.error( 'nonexistent syscall', token=syscall_descriptor) diff --git a/tools/parser_unittest.py b/tools/parser_unittest.py index 4fba590..f13a109 100755 --- a/tools/parser_unittest.py +++ b/tools/parser_unittest.py @@ -398,6 +398,24 @@ class ParseFilterStatementTests(unittest.TestCase): ), [ parser.Filter([[parser.Atom(0, '==', 0)]], bpf.Allow()), ])) + self.assertEqual( + self.parser.parse_filter_statement( + self._tokenize('io@libc: arg0 == 0')), + parser.ParsedFilterStatement(( + parser.Syscall('read', 0), + parser.Syscall('write', 1), + ), [ + parser.Filter([[parser.Atom(0, '==', 0)]], bpf.Allow()), + ])) + self.assertEqual( + self.parser.parse_filter_statement( + self._tokenize('file-io@systemd: arg0 == 0')), + parser.ParsedFilterStatement(( + parser.Syscall('read', 0), + parser.Syscall('write', 1), + ), [ + parser.Filter([[parser.Atom(0, '==', 0)]], bpf.Allow()), + ])) def test_parse_metadata(self): """Accept valid filter statements with metadata.""" @@ -418,6 +436,11 @@ class ParseFilterStatementTests(unittest.TestCase): def test_parse_unclosed_brace(self): """Reject unclosed brace.""" with self.assertRaisesRegex(parser.ParseException, 'unclosed brace'): + self.parser.parse_filter(self._tokenize('{ allow')) + + def test_parse_invalid_syscall_group(self): + """Reject invalid syscall groups.""" + with self.assertRaisesRegex(parser.ParseException, 'unclosed brace'): self.parser.parse_filter_statement( self._tokenize('{ read, write: arg0 == 0')) diff --git a/tools/testdata/arch_64.json b/tools/testdata/arch_64.json index 10c9855..385da94 100644 --- a/tools/testdata/arch_64.json +++ b/tools/testdata/arch_64.json @@ -109,5 +109,19 @@ "O_RDONLY": 0, "PROT_WRITE": 2, "PROT_EXEC": 4 + }, + "syscall_groups": { + "libc": { + "io": [ + "read", + "write" + ] + }, + "systemd": { + "file-io": [ + "read", + "write" + ] + } } } |