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"
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");
19 // This true for supported architectures (Intel and ARM EABI).
20 static_assert(MIN_SYSCALL
== 0u,
21 "min syscall should always be zero");
24 // SyscallRange represents an inclusive range of system call numbers.
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
},
35 // ARM EABI includes "ARM private" system calls starting at
36 // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
38 {MIN_PRIVATE_SYSCALL
, MAX_PRIVATE_SYSCALL
},
39 {MIN_GHOST_SYSCALL
, MAX_SYSCALL
},
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
) {
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
)) {
74 uint32_t SyscallSet::Iterator::operator*() const {
79 SyscallSet::Iterator
& SyscallSet::Iterator::operator++() {
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
) {
105 if (want_valid
&& num_
< range
.last
) {
108 if (want_invalid
&& num_
<= range
.last
) {
109 return range
.last
+ 1;
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
121 if (num_
< 0x7FFFFFFFu
)
123 if (num_
< 0x80000000u
)
126 if (num_
< 0xFFFFFFFFu
)
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