Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(631)

Side by Side Diff: sandbox/linux/seccomp-bpf/syscall_iterator.cc

Issue 903273002: Update from https://crrev.com/315085 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/syscall_iterator.h"
6
7 #include "base/logging.h"
8 #include "base/macros.h"
9 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
10
11 namespace sandbox {
12
13 namespace {
14
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
23
24 // SyscallRange represents an inclusive range of system call numbers.
25 struct SyscallRange {
26 uint32_t first;
27 uint32_t last;
28 };
29
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
41 };
42
43 } // namespace
44
45 SyscallSet::Iterator SyscallSet::begin() const {
46 return Iterator(set_, false);
47 }
48
49 SyscallSet::Iterator SyscallSet::end() const {
50 return Iterator(set_, true);
51 }
52
53 bool SyscallSet::IsValid(uint32_t num) {
54 for (const SyscallRange& range : kValidSyscallRanges) {
55 if (num >= range.first && num <= range.last) {
56 return true;
57 }
58 }
59 return false;
60 }
61
62 bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) {
63 return (lhs.set_ == rhs.set_);
64 }
65
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;
71 }
72 }
73
74 uint32_t SyscallSet::Iterator::operator*() const {
75 DCHECK(!done_);
76 return num_;
77 }
78
79 SyscallSet::Iterator& SyscallSet::Iterator::operator++() {
80 DCHECK(!done_);
81
82 num_ = NextSyscall();
83 if (num_ == 0) {
84 done_ = true;
85 }
86
87 return *this;
88 }
89
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);
95
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;
101 }
102 if (want_valid && num_ < range.first) {
103 return range.first;
104 }
105 if (want_valid && num_ < range.last) {
106 return num_ + 1;
107 }
108 if (want_invalid && num_ <= range.last) {
109 return range.last + 1;
110 }
111 }
112
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;
125
126 if (num_ < 0xFFFFFFFFu)
127 return 0xFFFFFFFFu;
128 }
129
130 return 0;
131 }
132
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_);
137 }
138
139 bool operator!=(const SyscallSet::Iterator& lhs,
140 const SyscallSet::Iterator& rhs) {
141 return !(lhs == rhs);
142 }
143
144 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/linux/seccomp-bpf/syscall_iterator.h ('k') | sandbox/linux/seccomp-bpf/syscall_iterator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698