1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "sandbox/linux/bpf_dsl/syscall_set.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include "base/macros.h" 11 #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h" 12 #include "sandbox/linux/tests/unit_tests.h" 13 14 namespace sandbox { 15 16 namespace { 17 18 const SyscallSet kSyscallSets[] = { 19 SyscallSet::All(), 20 SyscallSet::InvalidOnly(), 21 }; 22 23 SANDBOX_TEST(SyscallSet, Monotonous) { 24 for (const SyscallSet& set : kSyscallSets) { 25 uint32_t prev = 0; 26 bool have_prev = false; 27 for (uint32_t sysnum : set) { 28 if (have_prev) { 29 SANDBOX_ASSERT(sysnum > prev); 30 } else if (set == SyscallSet::All()) { 31 // The iterator should start at 0. 32 SANDBOX_ASSERT(sysnum == 0); 33 } 34 35 prev = sysnum; 36 have_prev = true; 37 } 38 39 // The iterator should always return 0xFFFFFFFFu as the last value. 40 SANDBOX_ASSERT(have_prev); 41 SANDBOX_ASSERT(prev == 0xFFFFFFFFu); 42 } 43 } 44 45 // AssertRange checks that SyscallIterator produces all system call 46 // numbers in the inclusive range [min, max]. 47 void AssertRange(uint32_t min, uint32_t max) { 48 SANDBOX_ASSERT(min < max); 49 uint32_t prev = min - 1; 50 for (uint32_t sysnum : SyscallSet::All()) { 51 if (sysnum >= min && sysnum <= max) { 52 SANDBOX_ASSERT(prev == sysnum - 1); 53 prev = sysnum; 54 } 55 } 56 SANDBOX_ASSERT(prev == max); 57 } 58 59 SANDBOX_TEST(SyscallSet, ValidSyscallRanges) { 60 AssertRange(MIN_SYSCALL, MAX_PUBLIC_SYSCALL); 61 #if defined(__arm__) 62 AssertRange(MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL); 63 AssertRange(MIN_GHOST_SYSCALL, MAX_SYSCALL); 64 #endif 65 } 66 67 SANDBOX_TEST(SyscallSet, InvalidSyscalls) { 68 static const uint32_t kExpected[] = { 69 #if defined(__mips__) 70 0, 71 MIN_SYSCALL - 1, 72 #endif 73 MAX_PUBLIC_SYSCALL + 1, 74 #if defined(__arm__) 75 MIN_PRIVATE_SYSCALL - 1, 76 MAX_PRIVATE_SYSCALL + 1, 77 MIN_GHOST_SYSCALL - 1, 78 MAX_SYSCALL + 1, 79 #endif 80 0x7FFFFFFFu, 81 0x80000000u, 82 0xFFFFFFFFu, 83 }; 84 85 for (const SyscallSet& set : kSyscallSets) { 86 size_t i = 0; 87 for (uint32_t sysnum : set) { 88 if (!SyscallSet::IsValid(sysnum)) { 89 SANDBOX_ASSERT(i < arraysize(kExpected)); 90 SANDBOX_ASSERT(kExpected[i] == sysnum); 91 ++i; 92 } 93 } 94 SANDBOX_ASSERT(i == arraysize(kExpected)); 95 } 96 } 97 98 SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) { 99 for (uint32_t sysnum : SyscallSet::ValidOnly()) { 100 SANDBOX_ASSERT(SyscallSet::IsValid(sysnum)); 101 } 102 } 103 104 SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) { 105 for (uint32_t sysnum : SyscallSet::InvalidOnly()) { 106 SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum)); 107 } 108 } 109 110 SANDBOX_TEST(SyscallSet, AllIsValidOnlyPlusInvalidOnly) { 111 std::vector<uint32_t> merged; 112 const SyscallSet valid_only = SyscallSet::ValidOnly(); 113 const SyscallSet invalid_only = SyscallSet::InvalidOnly(); 114 std::merge(valid_only.begin(), 115 valid_only.end(), 116 invalid_only.begin(), 117 invalid_only.end(), 118 std::back_inserter(merged)); 119 120 const SyscallSet all = SyscallSet::All(); 121 SANDBOX_ASSERT(merged == std::vector<uint32_t>(all.begin(), all.end())); 122 } 123 124 } // namespace 125 126 } // namespace sandbox 127