tools/compile_seccomp_policy: Parse filters
This change adds support for parsing filters.
Bug: chromium:856315
Test: ./tools/parser_unittest.py
Change-Id: I25926597564b5bf2d5af7d75d89c704b3b36b42a
diff --git a/tools/parser_unittest.py b/tools/parser_unittest.py
index 381c59c..6f190fb 100755
--- a/tools/parser_unittest.py
+++ b/tools/parser_unittest.py
@@ -24,6 +24,7 @@
import unittest
import arch
+import bpf
import parser # pylint: disable=wrong-import-order
ARCH_64 = arch.Arch.load_from_json(
@@ -97,7 +98,8 @@
def setUp(self):
self.arch = ARCH_64
- self.parser = parser.PolicyParser(self.arch)
+ self.parser = parser.PolicyParser(
+ self.arch, kill_action=bpf.KillProcess())
def _tokenize(self, line):
# pylint: disable=protected-access
@@ -234,21 +236,22 @@
class ParseFilterExpressionTests(unittest.TestCase):
- """Tests for PolicyParser.parse_filter_expression."""
+ """Tests for PolicyParser.parse_argument_expression."""
def setUp(self):
self.arch = ARCH_64
- self.parser = parser.PolicyParser(self.arch)
+ self.parser = parser.PolicyParser(
+ self.arch, kill_action=bpf.KillProcess())
def _tokenize(self, line):
# pylint: disable=protected-access
self.parser._parser_state.set_line(line)
return self.parser._parser_state.tokenize()
- def test_parse_filter_expression(self):
- """Accept valid filter expressions."""
+ def test_parse_argument_expression(self):
+ """Accept valid argument expressions."""
self.assertEqual(
- self.parser.parse_filter_expression(
+ self.parser.parse_argument_expression(
self._tokenize(
'arg0 in 0xffff || arg0 == PROT_EXEC && arg1 == PROT_WRITE'
)), [
@@ -257,31 +260,111 @@
parser.Atom(1, '==', 2)],
])
- def test_parse_empty_filter_expression(self):
- """Reject empty filter expressions."""
+ def test_parse_empty_argument_expression(self):
+ """Reject empty argument expressions."""
with self.assertRaisesRegex(parser.ParseException,
- 'empty filter expression'):
- self.parser.parse_filter_expression(
+ 'empty argument expression'):
+ self.parser.parse_argument_expression(
self._tokenize('arg0 in 0xffff ||'))
def test_parse_empty_clause(self):
"""Reject empty clause."""
with self.assertRaisesRegex(parser.ParseException, 'empty clause'):
- self.parser.parse_filter_expression(
+ self.parser.parse_argument_expression(
self._tokenize('arg0 in 0xffff &&'))
def test_parse_invalid_argument(self):
"""Reject invalid argument."""
with self.assertRaisesRegex(parser.ParseException, 'invalid argument'):
- self.parser.parse_filter_expression(
+ self.parser.parse_argument_expression(
self._tokenize('argX in 0xffff'))
def test_parse_invalid_operator(self):
"""Reject invalid operator."""
with self.assertRaisesRegex(parser.ParseException, 'invalid operator'):
- self.parser.parse_filter_expression(
+ self.parser.parse_argument_expression(
self._tokenize('arg0 = 0xffff'))
+class ParseFilterTests(unittest.TestCase):
+ """Tests for PolicyParser.parse_filter."""
+
+ def setUp(self):
+ self.arch = ARCH_64
+ self.parser = parser.PolicyParser(
+ self.arch, kill_action=bpf.KillProcess())
+
+ def _tokenize(self, line):
+ # pylint: disable=protected-access
+ self.parser._parser_state.set_line(line)
+ return self.parser._parser_state.tokenize()
+
+ def test_parse_filter(self):
+ """Accept valid filters."""
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('arg0 == 0')), [
+ parser.Filter([[parser.Atom(0, '==', 0)]], bpf.Allow()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('kill-process')), [
+ parser.Filter(None, bpf.KillProcess()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('kill-thread')), [
+ parser.Filter(None, bpf.KillThread()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('trap')), [
+ parser.Filter(None, bpf.Trap()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('return ENOSYS')), [
+ parser.Filter(None,
+ bpf.ReturnErrno(self.arch.constants['ENOSYS'])),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('trace')), [
+ parser.Filter(None, bpf.Trace()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('log')), [
+ parser.Filter(None, bpf.Log()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('allow')), [
+ parser.Filter(None, bpf.Allow()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(self._tokenize('1')), [
+ parser.Filter(None, bpf.Allow()),
+ ])
+ self.assertEqual(
+ self.parser.parse_filter(
+ self._tokenize(
+ '{ arg0 == 0, arg0 == 1; return ENOSYS, trap }')),
+ [
+ parser.Filter([[parser.Atom(0, '==', 0)]], bpf.Allow()),
+ parser.Filter([[parser.Atom(0, '==', 1)]],
+ bpf.ReturnErrno(self.arch.constants['ENOSYS'])),
+ parser.Filter(None, bpf.Trap()),
+ ])
+
+ def test_parse_missing_return_value(self):
+ """Reject missing return value."""
+ with self.assertRaisesRegex(parser.ParseException,
+ 'missing return value'):
+ self.parser.parse_filter(self._tokenize('return'))
+
+ def test_parse_invalid_return_value(self):
+ """Reject invalid return value."""
+ with self.assertRaisesRegex(parser.ParseException, 'invalid constant'):
+ self.parser.parse_filter(self._tokenize('return arg0'))
+
+ def test_parse_unclosed_brace(self):
+ """Reject unclosed brace."""
+ with self.assertRaisesRegex(parser.ParseException, 'unclosed brace'):
+ self.parser.parse_filter(self._tokenize('{ allow'))
+
+
if __name__ == '__main__':
unittest.main()