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/basictypes.h" 8 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h" 9 10 namespace sandbox { 11 12 uint32_t SyscallIterator::Next() { 13 if (done_) { 14 return num_; 15 } 16 17 uint32_t val; 18 do { 19 // |num_| has been initialized to 0, which we assume is also MIN_SYSCALL. 20 // This true for supported architectures (Intel and ARM EABI). 21 COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero); 22 val = num_; 23 24 // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL 25 // on Intel architectures, but leaves room for private syscalls on ARM. 26 if (num_ <= MAX_PUBLIC_SYSCALL) { 27 if (invalid_only_ && num_ < MAX_PUBLIC_SYSCALL) { 28 num_ = MAX_PUBLIC_SYSCALL; 29 } else { 30 ++num_; 31 } 32 #if defined(__arm__) 33 // ARM EABI includes "ARM private" system calls starting at 34 // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at 35 // MIN_GHOST_SYSCALL. 36 } else if (num_ < MIN_PRIVATE_SYSCALL - 1) { 37 num_ = MIN_PRIVATE_SYSCALL - 1; 38 } else if (num_ <= MAX_PRIVATE_SYSCALL) { 39 if (invalid_only_ && num_ < MAX_PRIVATE_SYSCALL) { 40 num_ = MAX_PRIVATE_SYSCALL; 41 } else { 42 ++num_; 43 } 44 } else if (num_ < MIN_GHOST_SYSCALL - 1) { 45 num_ = MIN_GHOST_SYSCALL - 1; 46 } else if (num_ <= MAX_SYSCALL) { 47 if (invalid_only_ && num_ < MAX_SYSCALL) { 48 num_ = MAX_SYSCALL; 49 } else { 50 ++num_; 51 } 52 #endif 53 // BPF programs only ever operate on unsigned quantities. So, that's how 54 // we iterate; we return values from 0..0xFFFFFFFFu. But there are places, 55 // where the kernel might interpret system call numbers as signed 56 // quantities, so the boundaries between signed and unsigned values are 57 // potential problem cases. We want to explicitly return these values from 58 // our iterator. 59 } else if (num_ < 0x7FFFFFFFu) { 60 num_ = 0x7FFFFFFFu; 61 } else if (num_ < 0x80000000u) { 62 num_ = 0x80000000u; 63 } else if (num_ < 0xFFFFFFFFu) { 64 num_ = 0xFFFFFFFFu; 65 } 66 } while (invalid_only_ && IsValid(val)); 67 68 done_ |= val == 0xFFFFFFFFu; 69 return val; 70 } 71 72 bool SyscallIterator::IsValid(uint32_t num) { 73 uint32_t min_syscall = MIN_SYSCALL; 74 if (num >= min_syscall && num <= MAX_PUBLIC_SYSCALL) { 75 return true; 76 } 77 if (IsArmPrivate(num)) { 78 return true; 79 } 80 return false; 81 } 82 83 #if defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__)) 84 bool SyscallIterator::IsArmPrivate(uint32_t num) { 85 return (num >= MIN_PRIVATE_SYSCALL && num <= MAX_PRIVATE_SYSCALL) || 86 (num >= MIN_GHOST_SYSCALL && num <= MAX_SYSCALL); 87 } 88 #else 89 bool SyscallIterator::IsArmPrivate(uint32_t) { return false; } 90 #endif 91 92 } // namespace sandbox 93