| 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 | 
|---|