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