xref: /aosp_15_r20/external/minijail/tools/seccomp_policy_lint_unittest.py (revision 4b9c6d91573e8b3a96609339b46361b5476dd0f9)
1#!/usr/bin/env python3
2#
3# Copyright (C) 2021 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16"""Unittests for the seccomp policy linter module."""
17
18from pathlib import Path
19import tempfile
20import unittest
21
22import seccomp_policy_lint
23
24class CheckSeccompPolicyTests(unittest.TestCase):
25    """Tests for check_seccomp_policy."""
26
27    def setUp(self):
28        self.tempdir = Path(tempfile.mkdtemp())
29
30    def _write_file(self, filename, contents):
31        """Helper to write out a file for testing."""
32        path = self.tempdir / filename
33        path.write_text(contents)
34        return path
35
36    def test_check_simple(self):
37        """Allow simple policy files."""
38        path = self._write_file(
39            'test.policy', """
40            # Comment.\n
41            read: 1\n
42            write: 1\n
43        """)
44
45        exp_out = seccomp_policy_lint.CheckPolicyReturn(
46                    f'seccomp: {path.resolve()} does not contain any dangerous'
47                    ' syscalls, so does not require review from'
48                    ' chromeos-security@',
49                    [])
50
51        with path.open('r', encoding='utf-8') as check_file:
52            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
53                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
54                    exp_out)
55
56    def test_check_dangerous_comment(self):
57        """Dangerous syscalls must have a comment and need to be reviewed."""
58        path = self._write_file(
59            'test.policy', """
60            # Comment.\n\n\n
61            clone: 1\n
62            write: 1\n
63        """)
64
65        exp_out = seccomp_policy_lint.CheckPolicyReturn(
66                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
67                    ' so requires review from chromeos-security@',
68                    [])
69
70        with path.open('r', encoding='utf-8') as check_file:
71            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
72                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
73                    exp_out)
74
75    def test_check_dangerous_no_comment(self):
76        """Dangerous syscalls without a comment should cause an error."""
77        path = self._write_file(
78            'test.policy', """
79            # Comment.\n
80            mount: 1\n
81            clone: 1\n
82        """)
83
84        exp_out = seccomp_policy_lint.CheckPolicyReturn(
85                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
86                    ' so requires review from chromeos-security@',
87                   [(f'{path.resolve()}, line 5: clone syscall is a dangerous '
88                   'syscall so requires a comment on the preceding line')])
89
90        with path.open('r', encoding='utf-8') as check_file:
91            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
92                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
93                    exp_out)
94
95    def test_check_duplicate_syscall(self):
96        """Policy files cannot have duplicate syscalls.."""
97        path = self._write_file(
98            'test.policy', """
99            # Comment.\n
100            clone: 1\n
101            clone: arg0 == 3
102        """)
103
104        exp_out = seccomp_policy_lint.CheckPolicyReturn(
105                    f'seccomp: {path.resolve()} contains dangerous syscalls,'
106                    ' so requires review from chromeos-security@',
107                   [(f'{path.resolve()}, line 5: repeat syscall: clone')])
108
109        with path.open('r', encoding='utf-8') as check_file:
110            self.assertEqual(seccomp_policy_lint.check_seccomp_policy(
111                    check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS),
112                    exp_out)
113
114
115if __name__ == '__main__':
116    unittest.main()
117