| OLD | NEW |
| (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 | |
| OLD | NEW |