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