1#!/usr/bin/env python3 2# Copyright 2020 The ChromiumOS Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6"""Unittests for the seccomp policy linter module.""" 7 8from pathlib import Path 9import tempfile 10import unittest 11 12import seccomp_policy_lint 13 14 15class CheckSeccompPolicyTests(unittest.TestCase): 16 """Tests for check_seccomp_policy.""" 17 18 def setUp(self): 19 self.tempdir = Path(tempfile.mkdtemp()) 20 21 def _write_file(self, filename, contents): 22 """Helper to write out a file for testing.""" 23 path = self.tempdir / filename 24 path.write_text(contents) 25 return path 26 27 def test_check_simple(self): 28 """Allow simple policy files.""" 29 path = self._write_file( 30 "test.policy", 31 """ 32 # Comment.\n 33 read: 1\n 34 write: 1\n 35 """, 36 ) 37 38 exp_out = seccomp_policy_lint.CheckPolicyReturn( 39 f"seccomp: {path.resolve()} does not contain any dangerous" 40 " syscalls, so does not require review from" 41 " chromeos-security@", 42 [], 43 ) 44 45 with path.open("r", encoding="utf-8") as check_file: 46 self.assertEqual( 47 seccomp_policy_lint.check_seccomp_policy( 48 check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS 49 ), 50 exp_out, 51 ) 52 53 def test_check_dangerous_comment(self): 54 """Dangerous syscalls must have a comment and need to be reviewed.""" 55 path = self._write_file( 56 "test.policy", 57 """ 58 # Comment.\n\n\n 59 clone: 1\n 60 write: 1\n 61 """, 62 ) 63 64 exp_out = seccomp_policy_lint.CheckPolicyReturn( 65 f"seccomp: {path.resolve()} contains dangerous syscalls," 66 " so requires review from chromeos-security@", 67 [], 68 ) 69 70 with path.open("r", encoding="utf-8") as check_file: 71 self.assertEqual( 72 seccomp_policy_lint.check_seccomp_policy( 73 check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS 74 ), 75 exp_out, 76 ) 77 78 def test_check_dangerous_no_comment(self): 79 """Dangerous syscalls without a comment should cause an error.""" 80 path = self._write_file( 81 "test.policy", 82 """ 83 # Comment.\n 84 mount: 1\n 85 clone: 1\n 86 """, 87 ) 88 89 exp_out = seccomp_policy_lint.CheckPolicyReturn( 90 f"seccomp: {path.resolve()} contains dangerous syscalls," 91 " so requires review from chromeos-security@", 92 [ 93 ( 94 f"{path.resolve()}:5:clone: syscall is dangerous " 95 "and requires a comment on the preceding line" 96 ) 97 ], 98 ) 99 100 with path.open("r", encoding="utf-8") as check_file: 101 self.assertEqual( 102 seccomp_policy_lint.check_seccomp_policy( 103 check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS 104 ), 105 exp_out, 106 ) 107 108 def test_check_duplicate_syscall(self): 109 """Policy files cannot have duplicate syscalls..""" 110 path = self._write_file( 111 "test.policy", 112 """ 113 # Comment.\n 114 clone: 1\n 115 clone: arg0 == 3 116 """, 117 ) 118 119 exp_out = seccomp_policy_lint.CheckPolicyReturn( 120 f"seccomp: {path.resolve()} contains dangerous syscalls," 121 " so requires review from chromeos-security@", 122 [f"{path.resolve()}:5:clone: duplicate entry found"], 123 ) 124 125 with path.open("r", encoding="utf-8") as check_file: 126 self.assertEqual( 127 seccomp_policy_lint.check_seccomp_policy( 128 check_file, seccomp_policy_lint.DANGEROUS_SYSCALLS 129 ), 130 exp_out, 131 ) 132 133 134if __name__ == "__main__": 135 unittest.main() 136