Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / sandbox / linux / bpf_dsl / syscall_set.cc
blob47810e99ac279762c43319b8ff9a8137f4d439c5
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/bpf_dsl/syscall_set.h"
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
11 namespace sandbox {
13 namespace {
15 #if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
16 // This is true for Mips O32 ABI.
17 static_assert(MIN_SYSCALL == __NR_Linux, "min syscall number should be 4000");
18 #else
19 // This true for supported architectures (Intel and ARM EABI).
20 static_assert(MIN_SYSCALL == 0u,
21 "min syscall should always be zero");
22 #endif
24 // SyscallRange represents an inclusive range of system call numbers.
25 struct SyscallRange {
26 uint32_t first;
27 uint32_t last;
30 const SyscallRange kValidSyscallRanges[] = {
31 // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL
32 // on Intel architectures, but leaves room for private syscalls on ARM.
33 {MIN_SYSCALL, MAX_PUBLIC_SYSCALL},
34 #if defined(__arm__)
35 // ARM EABI includes "ARM private" system calls starting at
36 // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
37 // MIN_GHOST_SYSCALL.
38 {MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL},
39 {MIN_GHOST_SYSCALL, MAX_SYSCALL},
40 #endif
43 } // namespace
45 SyscallSet::Iterator SyscallSet::begin() const {
46 return Iterator(set_, false);
49 SyscallSet::Iterator SyscallSet::end() const {
50 return Iterator(set_, true);
53 bool SyscallSet::IsValid(uint32_t num) {
54 for (const SyscallRange& range : kValidSyscallRanges) {
55 if (num >= range.first && num <= range.last) {
56 return true;
59 return false;
62 bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) {
63 return (lhs.set_ == rhs.set_);
66 SyscallSet::Iterator::Iterator(Set set, bool done)
67 : set_(set), done_(done), num_(0) {
68 // If the set doesn't contain 0, we need to skip to the next element.
69 if (!done && set_ == (IsValid(num_) ? Set::INVALID_ONLY : Set::VALID_ONLY)) {
70 ++*this;
74 uint32_t SyscallSet::Iterator::operator*() const {
75 DCHECK(!done_);
76 return num_;
79 SyscallSet::Iterator& SyscallSet::Iterator::operator++() {
80 DCHECK(!done_);
82 num_ = NextSyscall();
83 if (num_ == 0) {
84 done_ = true;
87 return *this;
90 // NextSyscall returns the next system call in the iterated system
91 // call set after |num_|, or 0 if no such system call exists.
92 uint32_t SyscallSet::Iterator::NextSyscall() const {
93 const bool want_valid = (set_ != Set::INVALID_ONLY);
94 const bool want_invalid = (set_ != Set::VALID_ONLY);
96 for (const SyscallRange& range : kValidSyscallRanges) {
97 if (want_invalid && range.first > 0 && num_ < range.first - 1) {
98 // Even when iterating invalid syscalls, we only include the end points;
99 // so skip directly to just before the next (valid) range.
100 return range.first - 1;
102 if (want_valid && num_ < range.first) {
103 return range.first;
105 if (want_valid && num_ < range.last) {
106 return num_ + 1;
108 if (want_invalid && num_ <= range.last) {
109 return range.last + 1;
113 if (want_invalid) {
114 // BPF programs only ever operate on unsigned quantities. So,
115 // that's how we iterate; we return values from
116 // 0..0xFFFFFFFFu. But there are places, where the kernel might
117 // interpret system call numbers as signed quantities, so the
118 // boundaries between signed and unsigned values are potential
119 // problem cases. We want to explicitly return these values from
120 // our iterator.
121 if (num_ < 0x7FFFFFFFu)
122 return 0x7FFFFFFFu;
123 if (num_ < 0x80000000u)
124 return 0x80000000u;
126 if (num_ < 0xFFFFFFFFu)
127 return 0xFFFFFFFFu;
130 return 0;
133 bool operator==(const SyscallSet::Iterator& lhs,
134 const SyscallSet::Iterator& rhs) {
135 DCHECK(lhs.set_ == rhs.set_);
136 return (lhs.done_ == rhs.done_) && (lhs.num_ == rhs.num_);
139 bool operator!=(const SyscallSet::Iterator& lhs,
140 const SyscallSet::Iterator& rhs) {
141 return !(lhs == rhs);
144 } // namespace sandbox