Home | History | Annotate | Download | only in seccomp-bpf
      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/linux_seccomp.h"
      6 #include "sandbox/linux/seccomp-bpf/port.h"
      7 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
      8 
      9 namespace playground2 {
     10 
     11 uint32_t SyscallIterator::Next() {
     12   if (done_) {
     13     return num_;
     14   }
     15 
     16   uint32_t val;
     17   do {
     18     // |num_| has been initialized to 0, which we assume is also MIN_SYSCALL.
     19     // This true for supported architectures (Intel and ARM EABI).
     20     COMPILE_ASSERT(MIN_SYSCALL == 0u,
     21                    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) {
     90   return false;
     91 }
     92 #endif
     93 
     94 }  // namespace
     95 
     96