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"
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
);
19 // This true for supported architectures (Intel and ARM EABI).
20 COMPILE_ASSERT(MIN_SYSCALL
== 0u, min_syscall_should_always_be_zero
);
23 // SyscallRange represents an inclusive range of system call numbers.
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
},
34 // ARM EABI includes "ARM private" system calls starting at
35 // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
37 {MIN_PRIVATE_SYSCALL
, MAX_PRIVATE_SYSCALL
},
38 {MIN_GHOST_SYSCALL
, MAX_SYSCALL
},
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
) {
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
)) {
73 uint32_t SyscallSet::Iterator::operator*() const {
78 SyscallSet::Iterator
& SyscallSet::Iterator::operator++() {
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
) {
104 if (want_valid
&& num_
< range
.last
) {
107 if (want_invalid
&& num_
<= range
.last
) {
108 return range
.last
+ 1;
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
120 if (num_
< 0x7FFFFFFFu
)
122 if (num_
< 0x80000000u
)
125 if (num_
< 0xFFFFFFFFu
)
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