• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 namespace sandbox {
11 
Next()12 uint32_t SyscallIterator::Next() {
13   if (done_) {
14     return num_;
15   }
16 
17   uint32_t val;
18   do {
19     // |num_| has been initialized to 0, which we assume is also MIN_SYSCALL.
20     // This true for supported architectures (Intel and ARM EABI).
21     COMPILE_ASSERT(MIN_SYSCALL == 0u, 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 
IsValid(uint32_t num)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__))
IsArmPrivate(uint32_t num)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
IsArmPrivate(uint32_t)89 bool SyscallIterator::IsArmPrivate(uint32_t) { return false; }
90 #endif
91 
92 }  // namespace sandbox
93