Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / sandbox / linux / seccomp-bpf / syscall_iterator.cc
index d1c383b..3590530 100644 (file)
 
 #include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
 
-#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/macros.h"
 #include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
 
 namespace sandbox {
 
-uint32_t SyscallIterator::Next() {
-  if (done_) {
-    return num_;
-  }
+namespace {
 
-  uint32_t val;
-  do {
 #if defined(__mips__) && (_MIPS_SIM == _MIPS_SIM_ABI32)
-    // |num_| has been initialized to 4000, which we assume is also MIN_SYSCALL.
-    // This is true for Mips O32 ABI.
-    COMPILE_ASSERT(MIN_SYSCALL == __NR_Linux, min_syscall_should_be_4000);
+// This is true for Mips O32 ABI.
+COMPILE_ASSERT(MIN_SYSCALL == __NR_Linux, min_syscall_should_be_4000);
 #else
-    // |num_| has been initialized to 0, which we assume is also MIN_SYSCALL.
-    // This true for supported architectures (Intel and ARM EABI).
-    COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero);
+// This true for supported architectures (Intel and ARM EABI).
+COMPILE_ASSERT(MIN_SYSCALL == 0u, min_syscall_should_always_be_zero);
 #endif
-    val = num_;
 
-    // The syscall iterator always starts at zero.
-    // If zero is not a valid system call, iterator first returns MIN_SYSCALL -1
-    // before continuing to iterate.
-    if (num_ == 0 && MIN_SYSCALL != num_) {
-      num_ = MIN_SYSCALL - 1;
+// SyscallRange represents an inclusive range of system call numbers.
+struct SyscallRange {
+  uint32_t first;
+  uint32_t last;
+};
+
+const SyscallRange kValidSyscallRanges[] = {
     // First we iterate up to MAX_PUBLIC_SYSCALL, which is equal to MAX_SYSCALL
     // on Intel architectures, but leaves room for private syscalls on ARM.
-    } else if (num_ <= MAX_PUBLIC_SYSCALL) {
-      if (invalid_only_ && num_ < MAX_PUBLIC_SYSCALL) {
-        num_ = MAX_PUBLIC_SYSCALL;
-      } else {
-        ++num_;
-      }
+    {MIN_SYSCALL, MAX_PUBLIC_SYSCALL},
 #if defined(__arm__)
-      // ARM EABI includes "ARM private" system calls starting at
-      // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
-      // MIN_GHOST_SYSCALL.
-    } else if (num_ < MIN_PRIVATE_SYSCALL - 1) {
-      num_ = MIN_PRIVATE_SYSCALL - 1;
-    } else if (num_ <= MAX_PRIVATE_SYSCALL) {
-      if (invalid_only_ && num_ < MAX_PRIVATE_SYSCALL) {
-        num_ = MAX_PRIVATE_SYSCALL;
-      } else {
-        ++num_;
-      }
-    } else if (num_ < MIN_GHOST_SYSCALL - 1) {
-      num_ = MIN_GHOST_SYSCALL - 1;
-    } else if (num_ <= MAX_SYSCALL) {
-      if (invalid_only_ && num_ < MAX_SYSCALL) {
-        num_ = MAX_SYSCALL;
-      } else {
-        ++num_;
-      }
+    // ARM EABI includes "ARM private" system calls starting at
+    // MIN_PRIVATE_SYSCALL, and a "ghost syscall private to the kernel" at
+    // MIN_GHOST_SYSCALL.
+    {MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL},
+    {MIN_GHOST_SYSCALL, MAX_SYSCALL},
 #endif
-      // BPF programs only ever operate on unsigned quantities. So, that's how
-      // we iterate; we return values from 0..0xFFFFFFFFu. But there are places,
-      // where the kernel might interpret system call numbers as signed
-      // quantities, so the boundaries between signed and unsigned values are
-      // potential problem cases. We want to explicitly return these values from
-      // our iterator.
-    } else if (num_ < 0x7FFFFFFFu) {
-      num_ = 0x7FFFFFFFu;
-    } else if (num_ < 0x80000000u) {
-      num_ = 0x80000000u;
-    } else if (num_ < 0xFFFFFFFFu) {
-      num_ = 0xFFFFFFFFu;
+};
+
+}  // namespace
+
+SyscallSet::Iterator SyscallSet::begin() const {
+  return Iterator(set_, false);
+}
+
+SyscallSet::Iterator SyscallSet::end() const {
+  return Iterator(set_, true);
+}
+
+bool SyscallSet::IsValid(uint32_t num) {
+  for (const SyscallRange& range : kValidSyscallRanges) {
+    if (num >= range.first && num <= range.last) {
+      return true;
     }
-  } while (invalid_only_ && IsValid(val));
+  }
+  return false;
+}
 
-  done_ |= val == 0xFFFFFFFFu;
-  return val;
+bool operator==(const SyscallSet& lhs, const SyscallSet& rhs) {
+  return (lhs.set_ == rhs.set_);
 }
 
-bool SyscallIterator::IsValid(uint32_t num) {
-  uint32_t min_syscall = MIN_SYSCALL;
-  if (num >= min_syscall && num <= MAX_PUBLIC_SYSCALL) {
-    return true;
+SyscallSet::Iterator::Iterator(Set set, bool done)
+    : set_(set), done_(done), num_(0) {
+  // If the set doesn't contain 0, we need to skip to the next element.
+  if (!done && set_ == (IsValid(num_) ? Set::INVALID_ONLY : Set::VALID_ONLY)) {
+    ++*this;
   }
-  if (IsArmPrivate(num)) {
-    return true;
+}
+
+uint32_t SyscallSet::Iterator::operator*() const {
+  DCHECK(!done_);
+  return num_;
+}
+
+SyscallSet::Iterator& SyscallSet::Iterator::operator++() {
+  DCHECK(!done_);
+
+  num_ = NextSyscall();
+  if (num_ == 0) {
+    done_ = true;
   }
-  return false;
+
+  return *this;
 }
 
-#if defined(__arm__) && (defined(__thumb__) || defined(__ARM_EABI__))
-bool SyscallIterator::IsArmPrivate(uint32_t num) {
-  return (num >= MIN_PRIVATE_SYSCALL && num <= MAX_PRIVATE_SYSCALL) ||
-         (num >= MIN_GHOST_SYSCALL && num <= MAX_SYSCALL);
+// NextSyscall returns the next system call in the iterated system
+// call set after |num_|, or 0 if no such system call exists.
+uint32_t SyscallSet::Iterator::NextSyscall() const {
+  const bool want_valid = (set_ != Set::INVALID_ONLY);
+  const bool want_invalid = (set_ != Set::VALID_ONLY);
+
+  for (const SyscallRange& range : kValidSyscallRanges) {
+    if (want_invalid && range.first > 0 && num_ < range.first - 1) {
+      // Even when iterating invalid syscalls, we only include the end points;
+      // so skip directly to just before the next (valid) range.
+      return range.first - 1;
+    }
+    if (want_valid && num_ < range.first) {
+      return range.first;
+    }
+    if (want_valid && num_ < range.last) {
+      return num_ + 1;
+    }
+    if (want_invalid && num_ <= range.last) {
+      return range.last + 1;
+    }
+  }
+
+  if (want_invalid) {
+    // BPF programs only ever operate on unsigned quantities. So,
+    // that's how we iterate; we return values from
+    // 0..0xFFFFFFFFu. But there are places, where the kernel might
+    // interpret system call numbers as signed quantities, so the
+    // boundaries between signed and unsigned values are potential
+    // problem cases. We want to explicitly return these values from
+    // our iterator.
+    if (num_ < 0x7FFFFFFFu)
+      return 0x7FFFFFFFu;
+    if (num_ < 0x80000000u)
+      return 0x80000000u;
+
+    if (num_ < 0xFFFFFFFFu)
+      return 0xFFFFFFFFu;
+  }
+
+  return 0;
+}
+
+bool operator==(const SyscallSet::Iterator& lhs,
+                const SyscallSet::Iterator& rhs) {
+  DCHECK(lhs.set_ == rhs.set_);
+  return (lhs.done_ == rhs.done_) && (lhs.num_ == rhs.num_);
+}
+
+bool operator!=(const SyscallSet::Iterator& lhs,
+                const SyscallSet::Iterator& rhs) {
+  return !(lhs == rhs);
 }
-#else
-bool SyscallIterator::IsArmPrivate(uint32_t) { return false; }
-#endif
 
 }  // namespace sandbox