// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "sandbox/linux/bpf_dsl/syscall_set.h" #include #include "sandbox/linux/bpf_dsl/linux_syscall_ranges.h" #include "sandbox/linux/tests/unit_tests.h" namespace sandbox { namespace { const SyscallSet kSyscallSets[] = { SyscallSet::All(), SyscallSet::InvalidOnly(), }; SANDBOX_TEST(SyscallSet, Monotonous) { for (const SyscallSet& set : kSyscallSets) { uint32_t prev = 0; bool have_prev = false; for (uint32_t sysnum : set) { if (have_prev) { SANDBOX_ASSERT(sysnum > prev); } else if (set == SyscallSet::All()) { // The iterator should start at 0. SANDBOX_ASSERT(sysnum == 0); } prev = sysnum; have_prev = true; } // The iterator should always return 0xFFFFFFFFu as the last value. SANDBOX_ASSERT(have_prev); SANDBOX_ASSERT(prev == 0xFFFFFFFFu); } } // AssertRange checks that SyscallIterator produces all system call // numbers in the inclusive range [min, max]. void AssertRange(uint32_t min, uint32_t max) { SANDBOX_ASSERT(min < max); uint32_t prev = min - 1; for (uint32_t sysnum : SyscallSet::All()) { if (sysnum >= min && sysnum <= max) { SANDBOX_ASSERT(prev == sysnum - 1); prev = sysnum; } } SANDBOX_ASSERT(prev == max); } SANDBOX_TEST(SyscallSet, ValidSyscallRanges) { AssertRange(MIN_SYSCALL, MAX_PUBLIC_SYSCALL); #if defined(__arm__) AssertRange(MIN_PRIVATE_SYSCALL, MAX_PRIVATE_SYSCALL); AssertRange(MIN_GHOST_SYSCALL, MAX_SYSCALL); #endif } SANDBOX_TEST(SyscallSet, InvalidSyscalls) { static const uint32_t kExpected[] = { #if defined(__mips__) 0, MIN_SYSCALL - 1, #endif MAX_PUBLIC_SYSCALL + 1, #if defined(__arm__) MIN_PRIVATE_SYSCALL - 1, MAX_PRIVATE_SYSCALL + 1, MIN_GHOST_SYSCALL - 1, MAX_SYSCALL + 1, #endif 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu, }; for (const SyscallSet& set : kSyscallSets) { size_t i = 0; for (uint32_t sysnum : set) { if (!SyscallSet::IsValid(sysnum)) { SANDBOX_ASSERT(i < arraysize(kExpected)); SANDBOX_ASSERT(kExpected[i] == sysnum); ++i; } } SANDBOX_ASSERT(i == arraysize(kExpected)); } } SANDBOX_TEST(SyscallSet, ValidOnlyIsOnlyValid) { for (uint32_t sysnum : SyscallSet::ValidOnly()) { SANDBOX_ASSERT(SyscallSet::IsValid(sysnum)); } } SANDBOX_TEST(SyscallSet, InvalidOnlyIsOnlyInvalid) { for (uint32_t sysnum : SyscallSet::InvalidOnly()) { SANDBOX_ASSERT(!SyscallSet::IsValid(sysnum)); } } SANDBOX_TEST(SyscallSet, AllIsValidOnlyPlusInvalidOnly) { std::vector merged; const SyscallSet valid_only = SyscallSet::ValidOnly(); const SyscallSet invalid_only = SyscallSet::InvalidOnly(); std::merge(valid_only.begin(), valid_only.end(), invalid_only.begin(), invalid_only.end(), std::back_inserter(merged)); const SyscallSet all = SyscallSet::All(); SANDBOX_ASSERT(merged == std::vector(all.begin(), all.end())); } } // namespace } // namespace sandbox