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/sandbox_bpf.h" |
| 6 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" |
| 7 |
| 8 #if defined(__i386__) || defined(__x86_64__) |
| 9 #define X32MASK 0x40000000u |
| 10 #else |
| 11 #define X32MASK 0 |
| 12 #endif |
| 13 |
| 14 namespace playground2 { |
| 15 |
| 16 uint32_t SyscallIterator::Next() { |
| 17 if (done_) { |
| 18 return num_; |
| 19 } |
| 20 uint32_t val; |
| 21 do { |
| 22 val = num_; |
| 23 |
| 24 // Zero might or might not be a valid system call. But we definitely want |
| 25 // to make sure that we return it from the iterator, as we ultimately must |
| 26 // compute system call ranges for BPF filtering that cover the entire |
| 27 // range 0..0xFFFFFFFFu. |
| 28 if (num_ == 0) { |
| 29 num_ = MIN_SYSCALL & ~X32MASK; |
| 30 |
| 31 // We generally want to start iterating from just outside of the |
| 32 // system call range and then continue past the end of the range. But |
| 33 // if system calls start at zero, that is not possible. |
| 34 // Also, if MIN_SYSCALL is zero, we have to increment by one in order |
| 35 // for our loop to make some progress. |
| 36 if (num_ == 0) { |
| 37 ++num_; |
| 38 } else if (num_ > 1) { |
| 39 --num_; |
| 40 } |
| 41 // Since this is platform-independent code, we iterate until |
| 42 // MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL on Intel architectures, |
| 43 // but leaves room for private syscalls on ARM. |
| 44 } else if (num_ <= (MAX_PUBLIC_SYSCALL & ~X32MASK)) { |
| 45 if (invalid_only_ && num_ < (MAX_PUBLIC_SYSCALL & ~X32MASK)) { |
| 46 num_ = MAX_PUBLIC_SYSCALL & ~X32MASK; |
| 47 } else { |
| 48 ++num_; |
| 49 } |
| 50 #if X32MASK |
| 51 // On Intel architectures, we might or might not have to worry about |
| 52 // system calls that set bit 30 to indicate the x32 ABI. It is generally |
| 53 // safe (albeit wasteful) for the system call iterator to iterate over |
| 54 // more system calls. So, we iterate over all possible MIN_SYSCALL.. |
| 55 // MAX_SYSCALL system calls, both with bit 30 cleared and bit 30 set. |
| 56 } else if (num_ < (MIN_SYSCALL | X32MASK) - 1) { |
| 57 num_ = (MIN_SYSCALL | X32MASK) - 1; |
| 58 } else if (num_ <= (MAX_SYSCALL | X32MASK)) { |
| 59 if (invalid_only_ && num_ < (MAX_SYSCALL | X32MASK)) { |
| 60 num_ = MAX_SYSCALL | X32MASK; |
| 61 } else { |
| 62 ++num_; |
| 63 } |
| 64 #elif defined(__arm__) |
| 65 // ARM EABI includes "ARM private" system calls starting at |
| 66 // |__ARM_NR_BASE|, and a "ghost syscall private to the kernel", cmpxchg, |
| 67 // at |__ARM_NR_BASE+0x00fff0|. |
| 68 // See </arch/arm/include/asm/unistd.h> in the Linux kernel. |
| 69 } else if (num_ < MIN_PRIVATE_SYSCALL - 1) { |
| 70 num_ = MIN_PRIVATE_SYSCALL - 1; |
| 71 } else if (num_ <= MAX_PRIVATE_SYSCALL) { |
| 72 if (invalid_only_ && num_ < MAX_PRIVATE_SYSCALL) { |
| 73 num_ = MAX_PRIVATE_SYSCALL; |
| 74 } else { |
| 75 ++num_; |
| 76 } |
| 77 } else if (num_ < __ARM_NR_cmpxchg - 1) { |
| 78 num_ = __ARM_NR_cmpxchg - 1; |
| 79 } else if (num_ <= MAX_SYSCALL) { |
| 80 if (invalid_only_ && num_ < MAX_SYSCALL) { |
| 81 num_ = MAX_SYSCALL; |
| 82 } else { |
| 83 ++num_; |
| 84 } |
| 85 #endif |
| 86 // BPF programs only ever operate on unsigned quantities. So, that's how |
| 87 // we iterate; we return values from 0..0xFFFFFFFFu. But there are places, |
| 88 // where the kernel might interpret system call numbers as signed |
| 89 // quantities, so the boundaries between signed and unsigned values are |
| 90 // potential problem cases. We want to explicitly return these values from |
| 91 // our iterator. |
| 92 } else if (num_ < 0x7FFFFFFFu) { |
| 93 num_ = 0x7FFFFFFFu; |
| 94 } else if (num_ < 0x80000000u) { |
| 95 num_ = 0x80000000u; |
| 96 } else if (num_ < 0xFFFFFFFFu) { |
| 97 num_ = 0xFFFFFFFFu; |
| 98 } |
| 99 } while (invalid_only_ && IsValid(val)); |
| 100 |
| 101 done_ |= val == 0xFFFFFFFFu; |
| 102 return val; |
| 103 } |
| 104 |
| 105 bool SyscallIterator::IsValid(uint32_t num) { |
| 106 uint32_t min_syscall = MIN_SYSCALL; |
| 107 if (num >= min_syscall && num <= MAX_PUBLIC_SYSCALL) { |
| 108 return true; |
| 109 } |
| 110 #if defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) |
| 111 if (num >= MIN_PRIVATE_SYSCALL && num <= MAX_PRIVATE_SYSCALL) { |
| 112 return true; |
| 113 } |
| 114 if (num >= __ARM_NR_cmpxchg && num <= MAX_SYSCALL) { |
| 115 return true; |
| 116 } |
| 117 #endif |
| 118 return false; |
| 119 } |
| 120 |
| 121 } // namespace |
OLD | NEW |