| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1b4e0678ab7b0fced954fa3c4291cbd456b5198b
|
| --- /dev/null
|
| +++ b/sandbox/linux/seccomp-bpf/syscall_iterator.cc
|
| @@ -0,0 +1,130 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
|
| +
|
| +namespace sandbox {
|
| +
|
| +namespace {
|
| +
|
| +#if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
|
| +// This is true for Mips O32 ABI.
|
| +COMPILE_ASSERT(MIN_SYSCALL == __NR_Linux, min_syscall_should_be_4000);
|
| +#else
|
| +// This true for supported architectures (Intel and ARM EABI).
|
| +COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero);
|
| +#endif
|
| +
|
| +// SyscallRange represents an inclusive range of system call numbers.
|
| +struct SyscallRange {
|
| + uint32_t first;
|
| + uint32_t last;
|
| +};
|
| +
|
| +const SyscallRange kValidSyscallRanges[] = {
|
| + // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL
|
| + // on Intel architectures, but leaves room for private syscalls on ARM.
|
| + {MIN_SYSCALL, MAX_PUBLIC_SYSCALL},
|
| +#if defined(__arm__)
|
| + // ARM EABI includes "ARM private" system calls starting at
|
| + // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
|
| + // MIN_GHOST_SYSCALL.
|
| + {MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL},
|
| + {MIN_GHOST_SYSCALL, MAX_SYSCALL},
|
| +#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 {
|
| + return Iterator(set_, false);
|
| +}
|
| +
|
| +SyscallSet::Iterator SyscallSet::end() const {
|
| + return Iterator(set_, true);
|
| +}
|
| +
|
| +bool SyscallSet::IsValid(uint32_t num) {
|
| + for (const SyscallRange& range : kValidSyscallRanges) {
|
| + if (num >= range.first && num <= range.last) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) {
|
| + return (lhs.set_ == rhs.set_);
|
| +}
|
| +
|
| +SyscallSet::Iterator::Iterator(Set set, bool done)
|
| + : set_(set), done_(done), num_(0) {
|
| + if (set_ == Set::INVALID_ONLY && !done_ && IsValid(num_)) {
|
| + ++*this;
|
| + }
|
| +}
|
| +
|
| +uint32_t SyscallSet::Iterator::operator*() const {
|
| + DCHECK(!done_);
|
| + return num_;
|
| +}
|
| +
|
| +SyscallSet::Iterator& SyscallSet::Iterator::operator++() {
|
| + DCHECK(!done_);
|
| +
|
| + num_ = NextSyscall(num_, set_ == Set::INVALID_ONLY);
|
| + if (num_ == 0) {
|
| + done_ = true;
|
| + }
|
| +
|
| + return *this;
|
| +}
|
| +
|
| +bool operator==(const SyscallSet::Iterator& lhs,
|
| + const SyscallSet::Iterator& rhs) {
|
| + DCHECK(lhs.set_ == rhs.set_);
|
| + return (lhs.done_ == rhs.done_) && (lhs.num_ == rhs.num_);
|
| +}
|
| +
|
| +bool operator!=(const SyscallSet::Iterator& lhs,
|
| + const SyscallSet::Iterator& rhs) {
|
| + return !(lhs == rhs);
|
| +}
|
| +
|
| +} // namespace sandbox
|
|
|