Home | History | Annotate | Download | only in bpf_dsl
      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/bpf_dsl/syscall_set.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 
     10 #include "base/macros.h"
     11 #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h"
     12 #include "sandbox/linux/tests/unit_tests.h"
     13 
     14 namespace sandbox {
     15 
     16 namespace {
     17 
     18 const SyscallSet kSyscallSets[] = {
     19     SyscallSet::All(),
     20     SyscallSet::InvalidOnly(),
     21 };
     22 
     23 SANDBOX_TEST(SyscallSet, Monotonous) {
     24   for (const SyscallSet& set : kSyscallSets) {
     25     uint32_t prev = 0;
     26     bool have_prev = false;
     27     for (uint32_t sysnum : set) {
     28       if (have_prev) {
     29         SANDBOX_ASSERT(sysnum > prev);
     30       } else if (set == SyscallSet::All()) {
     31         // The iterator should start at 0.
     32         SANDBOX_ASSERT(sysnum == 0);
     33       }
     34 
     35       prev = sysnum;
     36       have_prev = true;
     37     }
     38 
     39     // The iterator should always return 0xFFFFFFFFu as the last value.
     40     SANDBOX_ASSERT(have_prev);
     41     SANDBOX_ASSERT(prev == 0xFFFFFFFFu);
     42   }
     43 }
     44 
     45 // AssertRange checks that SyscallIterator produces all system call
     46 // numbers in the inclusive range [min, max].
     47 void AssertRange(uint32_t min, uint32_t max) {
     48   SANDBOX_ASSERT(min < max);
     49   uint32_t prev = min - 1;
     50   for (uint32_t sysnum : SyscallSet::All()) {
     51     if (sysnum >= min && sysnum <= max) {
     52       SANDBOX_ASSERT(prev == sysnum - 1);
     53       prev = sysnum;
     54     }
     55   }
     56   SANDBOX_ASSERT(prev == max);
     57 }
     58 
     59 SANDBOX_TEST(SyscallSet, ValidSyscallRanges) {
     60   AssertRange(MIN_SYSCALL, MAX_PUBLIC_SYSCALL);
     61 #if defined(__arm__)
     62   AssertRange(MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL);
     63   AssertRange(MIN_GHOST_SYSCALL, MAX_SYSCALL);
     64 #endif
     65 }
     66 
     67 SANDBOX_TEST(SyscallSet, InvalidSyscalls) {
     68   static const uint32_t kExpected[] = {
     69 #if defined(__mips__)
     70     0,
     71     MIN_SYSCALL - 1,
     72 #endif
     73     MAX_PUBLIC_SYSCALL + 1,
     74 #if defined(__arm__)
     75     MIN_PRIVATE_SYSCALL - 1,
     76     MAX_PRIVATE_SYSCALL + 1,
     77     MIN_GHOST_SYSCALL - 1,
     78     MAX_SYSCALL + 1,
     79 #endif
     80     0x7FFFFFFFu,
     81     0x80000000u,
     82     0xFFFFFFFFu,
     83   };
     84 
     85   for (const SyscallSet& set : kSyscallSets) {
     86     size_t i = 0;
     87     for (uint32_t sysnum : set) {
     88       if (!SyscallSet::IsValid(sysnum)) {
     89         SANDBOX_ASSERT(i < arraysize(kExpected));
     90         SANDBOX_ASSERT(kExpected[i] == sysnum);
     91         ++i;
     92       }
     93     }
     94     SANDBOX_ASSERT(i == arraysize(kExpected));
     95   }
     96 }
     97 
     98 SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) {
     99   for (uint32_t sysnum : SyscallSet::ValidOnly()) {
    100     SANDBOX_ASSERT(SyscallSet::IsValid(sysnum));
    101   }
    102 }
    103 
    104 SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) {
    105   for (uint32_t sysnum : SyscallSet::InvalidOnly()) {
    106     SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum));
    107   }
    108 }
    109 
    110 SANDBOX_TEST(SyscallSet, AllIsValidOnlyPlusInvalidOnly) {
    111   std::vector<uint32_t> merged;
    112   const SyscallSet valid_only = SyscallSet::ValidOnly();
    113   const SyscallSet invalid_only = SyscallSet::InvalidOnly();
    114   std::merge(valid_only.begin(),
    115              valid_only.end(),
    116              invalid_only.begin(),
    117              invalid_only.end(),
    118              std::back_inserter(merged));
    119 
    120   const SyscallSet all = SyscallSet::All();
    121   SANDBOX_ASSERT(merged == std::vector<uint32_t>(all.begin(), all.end()));
    122 }
    123 
    124 }  // namespace
    125 
    126 }  // namespace sandbox
    127