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/sandbox_bpf.h"
6#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
7#include "sandbox/linux/tests/unit_tests.h"
8
9namespace sandbox {
10
11namespace {
12
13SANDBOX_TEST(SyscallIterator, Monotonous) {
14  for (int i = 0; i < 2; ++i) {
15    bool invalid_only = !i;  // Testing both |invalid_only| cases.
16    SyscallIterator iter(invalid_only);
17    uint32_t next = iter.Next();
18
19    if (!invalid_only) {
20      // The iterator should start at 0.
21      SANDBOX_ASSERT(next == 0);
22    }
23    for (uint32_t last = next; !iter.Done(); last = next) {
24      next = iter.Next();
25      SANDBOX_ASSERT(last < next);
26    }
27    // The iterator should always return 0xFFFFFFFFu as the last value.
28    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
29  }
30}
31
32SANDBOX_TEST(SyscallIterator, PublicSyscallRange) {
33  SyscallIterator iter(false);
34  uint32_t next = iter.Next();
35
36  // The iterator should cover the public syscall range
37  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
38  // We're assuming MIN_SYSCALL == 0 for all architectures,
39  // this is currently valid for Intel and ARM EABI.
40  SANDBOX_ASSERT(MIN_SYSCALL == 0);
41  SANDBOX_ASSERT(next == MIN_SYSCALL);
42  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
43    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
44  }
45  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
46}
47
48#if defined(__arm__)
49SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) {
50  SyscallIterator iter(false);
51  uint32_t next = iter.Next();
52  while (next < MIN_PRIVATE_SYSCALL - 1) {
53    next = iter.Next();
54  }
55  // The iterator should cover the ARM private syscall range
56  // without skipping syscalls.
57  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
58  for (uint32_t last = next; next < MAX_PRIVATE_SYSCALL + 1; last = next) {
59    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
60  }
61  SANDBOX_ASSERT(next == MAX_PRIVATE_SYSCALL + 1);
62}
63
64SANDBOX_TEST(SyscallIterator, ARMHiddenSyscallRange) {
65  SyscallIterator iter(false);
66  uint32_t next = iter.Next();
67  while (next < MIN_GHOST_SYSCALL - 1) {
68    next = iter.Next();
69  }
70  // The iterator should cover the ARM hidden syscall range
71  // without skipping syscalls.
72  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
73  for (uint32_t last = next; next < MAX_SYSCALL + 1; last = next) {
74    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
75  }
76  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
77}
78#endif
79
80SANDBOX_TEST(SyscallIterator, Invalid) {
81  for (int i = 0; i < 2; ++i) {
82    bool invalid_only = !i;  // Testing both |invalid_only| cases.
83    SyscallIterator iter(invalid_only);
84    uint32_t next = iter.Next();
85
86    while (next < MAX_SYSCALL + 1) {
87      next = iter.Next();
88    }
89
90    SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
91    while (next < 0x7FFFFFFFu) {
92      next = iter.Next();
93    }
94
95    // The iterator should return the signed/unsigned corner cases.
96    SANDBOX_ASSERT(next == 0x7FFFFFFFu);
97    next = iter.Next();
98    SANDBOX_ASSERT(next == 0x80000000u);
99    SANDBOX_ASSERT(!iter.Done());
100    next = iter.Next();
101    SANDBOX_ASSERT(iter.Done());
102    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
103  }
104}
105
106SANDBOX_TEST(SyscallIterator, InvalidOnly) {
107  bool invalid_only = true;
108  SyscallIterator iter(invalid_only);
109  uint32_t next = iter.Next();
110  // We're assuming MIN_SYSCALL == 0 for all architectures,
111  // this is currently valid for Intel and ARM EABI.
112  // First invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
113  SANDBOX_ASSERT(MIN_SYSCALL == 0);
114  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
115
116#if defined(__arm__)
117  next = iter.Next();
118  // The iterator should skip until the last invalid syscall in this range.
119  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
120  while (next <= MAX_PRIVATE_SYSCALL) {
121    next = iter.Next();
122  }
123
124  next = iter.Next();
125  // The iterator should skip until the last invalid syscall in this range.
126  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
127  while (next <= MAX_SYSCALL) {
128    next = iter.Next();
129  }
130  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
131#endif
132}
133
134}  // namespace
135
136}  // namespace sandbox
137