• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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