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/seccomp-bpf/syscall_iterator.h"
6
7#include <stdint.h>
8
9#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
10#include "sandbox/linux/tests/unit_tests.h"
11
12namespace sandbox {
13
14namespace {
15
16SANDBOX_TEST(SyscallIterator, Monotonous) {
17  for (int i = 0; i < 2; ++i) {
18    bool invalid_only = !i;  // Testing both |invalid_only| cases.
19    SyscallIterator iter(invalid_only);
20    uint32_t next = iter.Next();
21
22    if (!invalid_only) {
23      // The iterator should start at 0.
24      SANDBOX_ASSERT(next == 0);
25    }
26    for (uint32_t last = next; !iter.Done(); last = next) {
27      next = iter.Next();
28      SANDBOX_ASSERT(last < next);
29    }
30    // The iterator should always return 0xFFFFFFFFu as the last value.
31    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
32  }
33}
34
35#if defined(__mips__)
36SANDBOX_TEST(SyscallIterator, PublicSyscallRangeMIPS) {
37  SyscallIterator iter(false);
38  uint32_t next = iter.Next();
39  SANDBOX_ASSERT(next == 0);
40
41  // Since on MIPS MIN_SYSCALL != 0 we need to move iterator to valid range.
42  next = iter.Next();
43  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
44
45  // The iterator should cover the public syscall range
46  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
47  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
48    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
49  }
50  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
51}
52#else
53SANDBOX_TEST(SyscallIterator, PublicSyscallRangeIntelArm) {
54  SyscallIterator iter(false);
55  uint32_t next = iter.Next();
56
57  // The iterator should cover the public syscall range
58  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
59  // We're assuming MIN_SYSCALL == 0 for all architectures,
60  // this is currently valid for Intel and ARM EABI.
61  SANDBOX_ASSERT(MIN_SYSCALL == 0);
62  SANDBOX_ASSERT(next == MIN_SYSCALL);
63  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
64    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
65  }
66  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
67}
68#endif  // defined(__mips__)
69
70#if defined(__arm__)
71SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) {
72  SyscallIterator iter(false);
73  uint32_t next = iter.Next();
74  while (next < MIN_PRIVATE_SYSCALL - 1) {
75    next = iter.Next();
76  }
77  // The iterator should cover the ARM private syscall range
78  // without skipping syscalls.
79  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
80  for (uint32_t last = next; next < MAX_PRIVATE_SYSCALL + 1; last = next) {
81    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
82  }
83  SANDBOX_ASSERT(next == MAX_PRIVATE_SYSCALL + 1);
84}
85
86SANDBOX_TEST(SyscallIterator, ARMHiddenSyscallRange) {
87  SyscallIterator iter(false);
88  uint32_t next = iter.Next();
89  while (next < MIN_GHOST_SYSCALL - 1) {
90    next = iter.Next();
91  }
92  // The iterator should cover the ARM hidden syscall range
93  // without skipping syscalls.
94  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
95  for (uint32_t last = next; next < MAX_SYSCALL + 1; last = next) {
96    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
97  }
98  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
99}
100#endif
101
102SANDBOX_TEST(SyscallIterator, Invalid) {
103  for (int i = 0; i < 2; ++i) {
104    bool invalid_only = !i;  // Testing both |invalid_only| cases.
105    SyscallIterator iter(invalid_only);
106    uint32_t next = iter.Next();
107
108    while (next < MAX_SYSCALL + 1) {
109      next = iter.Next();
110    }
111
112    SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
113    while (next < 0x7FFFFFFFu) {
114      next = iter.Next();
115    }
116
117    // The iterator should return the signed/unsigned corner cases.
118    SANDBOX_ASSERT(next == 0x7FFFFFFFu);
119    next = iter.Next();
120    SANDBOX_ASSERT(next == 0x80000000u);
121    SANDBOX_ASSERT(!iter.Done());
122    next = iter.Next();
123    SANDBOX_ASSERT(iter.Done());
124    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
125  }
126}
127
128#if defined(__mips__)
129SANDBOX_TEST(SyscallIterator, InvalidOnlyMIPS) {
130  bool invalid_only = true;
131  SyscallIterator iter(invalid_only);
132  uint32_t next = iter.Next();
133  SANDBOX_ASSERT(next == 0);
134  // For Mips O32 ABI we're assuming MIN_SYSCALL == 4000.
135  SANDBOX_ASSERT(MIN_SYSCALL == 4000);
136
137  // Since on MIPS MIN_SYSCALL != 0, we need to move iterator to valid range
138  // The iterator should skip until the last invalid syscall in this range.
139  next = iter.Next();
140  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
141  next = iter.Next();
142  // First next invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
143  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
144}
145
146#else
147
148SANDBOX_TEST(SyscallIterator, InvalidOnlyIntelArm) {
149  bool invalid_only = true;
150  SyscallIterator iter(invalid_only);
151  uint32_t next = iter.Next();
152  // We're assuming MIN_SYSCALL == 0 for all architectures,
153  // this is currently valid for Intel and ARM EABI.
154  // First invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
155  SANDBOX_ASSERT(MIN_SYSCALL == 0);
156  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
157
158#if defined(__arm__)
159  next = iter.Next();
160  // The iterator should skip until the last invalid syscall in this range.
161  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
162  while (next <= MAX_PRIVATE_SYSCALL) {
163    next = iter.Next();
164  }
165
166  next = iter.Next();
167  // The iterator should skip until the last invalid syscall in this range.
168  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
169  while (next <= MAX_SYSCALL) {
170    next = iter.Next();
171  }
172  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
173#endif  // defined(__arm__)
174}
175#endif  // defined(__mips__)
176
177}  // namespace
178
179}  // namespace sandbox
180