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