Index: sandbox/linux/seccomp-bpf/syscall_iterator.cc |
diff --git a/sandbox/linux/seccomp-bpf/syscall_iterator.cc b/sandbox/linux/seccomp-bpf/syscall_iterator.cc |
index 1b4e0678ab7b0fced954fa3c4291cbd456b5198b..35905309f47d5c823deb1420ec6f8ede472b4edc 100644 |
--- a/sandbox/linux/seccomp-bpf/syscall_iterator.cc |
+++ b/sandbox/linux/seccomp-bpf/syscall_iterator.cc |
@@ -39,37 +39,6 @@ const SyscallRange kValidSyscallRanges[] = { |
#endif |
}; |
-// NextSyscall returns the next system call in the specified system |
-// call set after |cur|, or 0 if no such system call exists. |
-uint32_t NextSyscall(uint32_t cur, bool invalid_only) { |
- for (const SyscallRange& range : kValidSyscallRanges) { |
- if (range.first > 0 && cur < range.first - 1) { |
- return range.first - 1; |
- } |
- if (cur <= range.last) { |
- if (invalid_only) { |
- return range.last + 1; |
- } |
- return cur + 1; |
- } |
- } |
- |
- // BPF programs only ever operate on unsigned quantities. So, that's how |
- // we iterate; we return values from 0..0xFFFFFFFFu. But there are places, |
- // where the kernel might interpret system call numbers as signed |
- // quantities, so the boundaries between signed and unsigned values are |
- // potential problem cases. We want to explicitly return these values from |
- // our iterator. |
- if (cur < 0x7FFFFFFFu) |
- return 0x7FFFFFFFu; |
- if (cur < 0x80000000u) |
- return 0x80000000u; |
- |
- if (cur < 0xFFFFFFFFu) |
- return 0xFFFFFFFFu; |
- return 0; |
-} |
- |
} // namespace |
SyscallSet::Iterator SyscallSet::begin() const { |
@@ -95,7 +64,8 @@ bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) { |
SyscallSet::Iterator::Iterator(Set set, bool done) |
: set_(set), done_(done), num_(0) { |
- if (set_ == Set::INVALID_ONLY && !done_ && IsValid(num_)) { |
+ // If the set doesn't contain 0, we need to skip to the next element. |
+ if (!done && set_ == (IsValid(num_) ? Set::INVALID_ONLY : Set::VALID_ONLY)) { |
++*this; |
} |
} |
@@ -108,7 +78,7 @@ uint32_t SyscallSet::Iterator::operator*() const { |
SyscallSet::Iterator& SyscallSet::Iterator::operator++() { |
DCHECK(!done_); |
- num_ = NextSyscall(num_, set_ == Set::INVALID_ONLY); |
+ num_ = NextSyscall(); |
if (num_ == 0) { |
done_ = true; |
} |
@@ -116,6 +86,49 @@ SyscallSet::Iterator& SyscallSet::Iterator::operator++() { |
return *this; |
} |
+// NextSyscall returns the next system call in the iterated system |
+// call set after |num_|, or 0 if no such system call exists. |
+uint32_t SyscallSet::Iterator::NextSyscall() const { |
+ const bool want_valid = (set_ != Set::INVALID_ONLY); |
+ const bool want_invalid = (set_ != Set::VALID_ONLY); |
+ |
+ for (const SyscallRange& range : kValidSyscallRanges) { |
+ if (want_invalid && range.first > 0 && num_ < range.first - 1) { |
+ // Even when iterating invalid syscalls, we only include the end points; |
+ // so skip directly to just before the next (valid) range. |
+ return range.first - 1; |
+ } |
+ if (want_valid && num_ < range.first) { |
+ return range.first; |
+ } |
+ if (want_valid && num_ < range.last) { |
+ return num_ + 1; |
+ } |
+ if (want_invalid && num_ <= range.last) { |
+ return range.last + 1; |
+ } |
+ } |
+ |
+ if (want_invalid) { |
+ // BPF programs only ever operate on unsigned quantities. So, |
+ // that's how we iterate; we return values from |
+ // 0..0xFFFFFFFFu. But there are places, where the kernel might |
+ // interpret system call numbers as signed quantities, so the |
+ // boundaries between signed and unsigned values are potential |
+ // problem cases. We want to explicitly return these values from |
+ // our iterator. |
+ if (num_ < 0x7FFFFFFFu) |
+ return 0x7FFFFFFFu; |
+ if (num_ < 0x80000000u) |
+ return 0x80000000u; |
+ |
+ if (num_ < 0xFFFFFFFFu) |
+ return 0xFFFFFFFFu; |
+ } |
+ |
+ return 0; |
+} |
+ |
bool operator==(const SyscallSet::Iterator& lhs, |
const SyscallSet::Iterator& rhs) { |
DCHECK(lhs.set_ == rhs.set_); |