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
SANDBOX_TEST(SyscallSet,Monotonous)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].
AssertRange(uint32_t min,uint32_t 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
SANDBOX_TEST(SyscallSet,ValidSyscallRanges)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
SANDBOX_TEST(SyscallSet,InvalidSyscalls)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
SANDBOX_TEST(SyscallSet,ValidOnlyIsOnlyValid)98 SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) {
99 for (uint32_t sysnum : SyscallSet::ValidOnly()) {
100 SANDBOX_ASSERT(SyscallSet::IsValid(sysnum));
101 }
102 }
103
SANDBOX_TEST(SyscallSet,InvalidOnlyIsOnlyInvalid)104 SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) {
105 for (uint32_t sysnum : SyscallSet::InvalidOnly()) {
106 SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum));
107 }
108 }
109
SANDBOX_TEST(SyscallSet,AllIsValidOnlyPlusInvalidOnly)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