#!/usr/bin/env python3 # # Copyright (C) 2021 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Unittests for the seccomp policy linter module.""" from pathlib import Path import tempfile import unittest import seccomp_policy_lint class CheckSeccompPolicyTests(unittest.TestCase): """Tests for check_seccomp_policy.""" def setUp(self): self.tempdir = Path(tempfile.mkdtemp()) def _write_file(self, filename, contents): """Helper to write out a file for testing.""" path = self.tempdir / filename path.write_text(contents) return path def test_check_simple(self): """Allow simple policy files.""" path = self._write_file( 'test.policy', """ # Comment.\n read: 1\n write: 1\n """) exp_out = seccomp_policy_lint.CheckPolicyReturn( f'seccomp: {path.resolve()} does not contain any dangerous' ' syscalls, so does not require review from' ' chromeos-security@', []) with path.open('r', encoding='utf-8') as check_file: self.assertEqual(seccomp_policy_lint.check_seccomp_policy( check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS), exp_out) def test_check_dangerous_comment(self): """Dangerous syscalls must have a comment and need to be reviewed.""" path = self._write_file( 'test.policy', """ # Comment.\n\n\n clone: 1\n write: 1\n """) exp_out = seccomp_policy_lint.CheckPolicyReturn( f'seccomp: {path.resolve()} contains dangerous syscalls,' ' so requires review from chromeos-security@', []) with path.open('r', encoding='utf-8') as check_file: self.assertEqual(seccomp_policy_lint.check_seccomp_policy( check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS), exp_out) def test_check_dangerous_no_comment(self): """Dangerous syscalls without a comment should cause an error.""" path = self._write_file( 'test.policy', """ # Comment.\n mount: 1\n clone: 1\n """) exp_out = seccomp_policy_lint.CheckPolicyReturn( f'seccomp: {path.resolve()} contains dangerous syscalls,' ' so requires review from chromeos-security@', [(f'{path.resolve()}, line 5: clone syscall is a dangerous ' 'syscall so requires a comment on the preceding line')]) with path.open('r', encoding='utf-8') as check_file: self.assertEqual(seccomp_policy_lint.check_seccomp_policy( check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS), exp_out) def test_check_duplicate_syscall(self): """Policy files cannot have duplicate syscalls..""" path = self._write_file( 'test.policy', """ # Comment.\n clone: 1\n clone: arg0 == 3 """) exp_out = seccomp_policy_lint.CheckPolicyReturn( f'seccomp: {path.resolve()} contains dangerous syscalls,' ' so requires review from chromeos-security@', [(f'{path.resolve()}, line 5: repeat syscall: clone')]) with path.open('r', encoding='utf-8') as check_file: self.assertEqual(seccomp_policy_lint.check_seccomp_policy( check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS), exp_out) if __name__ == '__main__': unittest.main()