Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / sandbox / linux / seccomp-bpf / syscall_iterator.cc
blob35905309f47d5c823deb1420ec6f8ede472b4edc
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.
5 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
11 namespace sandbox {
13 namespace {
15 #if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
16 // This is true for Mips O32 ABI.
17 COMPILE_ASSERT(MIN_SYSCALL == __NR_Linux, min_syscall_should_be_4000);
18 #else
19 // This true for supported architectures (Intel and ARM EABI).
20 COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero);
21 #endif
23 // SyscallRange represents an inclusive range of system call numbers.
24 struct SyscallRange {
25 uint32_t first;
26 uint32_t last;
29 const SyscallRange kValidSyscallRanges[] = {
30 // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL
31 // on Intel architectures, but leaves room for private syscalls on ARM.
32 {MIN_SYSCALL, MAX_PUBLIC_SYSCALL},
33 #if defined(__arm__)
34 // ARM EABI includes "ARM private" system calls starting at
35 // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
36 // MIN_GHOST_SYSCALL.
37 {MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL},
38 {MIN_GHOST_SYSCALL, MAX_SYSCALL},
39 #endif
42 } // namespace
44 SyscallSet::Iterator SyscallSet::begin() const {
45 return Iterator(set_, false);
48 SyscallSet::Iterator SyscallSet::end() const {
49 return Iterator(set_, true);
52 bool SyscallSet::IsValid(uint32_t num) {
53 for (const SyscallRange& range : kValidSyscallRanges) {
54 if (num >= range.first && num <= range.last) {
55 return true;
58 return false;
61 bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) {
62 return (lhs.set_ == rhs.set_);
65 SyscallSet::Iterator::Iterator(Set set, bool done)
66 : set_(set), done_(done), num_(0) {
67 // If the set doesn't contain 0, we need to skip to the next element.
68 if (!done && set_ == (IsValid(num_) ? Set::INVALID_ONLY : Set::VALID_ONLY)) {
69 ++*this;
73 uint32_t SyscallSet::Iterator::operator*() const {
74 DCHECK(!done_);
75 return num_;
78 SyscallSet::Iterator& SyscallSet::Iterator::operator++() {
79 DCHECK(!done_);
81 num_ = NextSyscall();
82 if (num_ == 0) {
83 done_ = true;
86 return *this;
89 // NextSyscall returns the next system call in the iterated system
90 // call set after |num_|, or 0 if no such system call exists.
91 uint32_t SyscallSet::Iterator::NextSyscall() const {
92 const bool want_valid = (set_ != Set::INVALID_ONLY);
93 const bool want_invalid = (set_ != Set::VALID_ONLY);
95 for (const SyscallRange& range : kValidSyscallRanges) {
96 if (want_invalid && range.first > 0 && num_ < range.first - 1) {
97 // Even when iterating invalid syscalls, we only include the end points;
98 // so skip directly to just before the next (valid) range.
99 return range.first - 1;
101 if (want_valid && num_ < range.first) {
102 return range.first;
104 if (want_valid && num_ < range.last) {
105 return num_ + 1;
107 if (want_invalid && num_ <= range.last) {
108 return range.last + 1;
112 if (want_invalid) {
113 // BPF programs only ever operate on unsigned quantities. So,
114 // that's how we iterate; we return values from
115 // 0..0xFFFFFFFFu. But there are places, where the kernel might
116 // interpret system call numbers as signed quantities, so the
117 // boundaries between signed and unsigned values are potential
118 // problem cases. We want to explicitly return these values from
119 // our iterator.
120 if (num_ < 0x7FFFFFFFu)
121 return 0x7FFFFFFFu;
122 if (num_ < 0x80000000u)
123 return 0x80000000u;
125 if (num_ < 0xFFFFFFFFu)
126 return 0xFFFFFFFFu;
129 return 0;
132 bool operator==(const SyscallSet::Iterator& lhs,
133 const SyscallSet::Iterator& rhs) {
134 DCHECK(lhs.set_ == rhs.set_);
135 return (lhs.done_ == rhs.done_) && (lhs.num_ == rhs.num_);
138 bool operator!=(const SyscallSet::Iterator& lhs,
139 const SyscallSet::Iterator& rhs) {
140 return !(lhs == rhs);
143 } // namespace sandbox