// 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/seccomp-bpf/sandbox_bpf.h" #include "sandbox/linux/seccomp-bpf/syscall_iterator.h" #include "sandbox/linux/tests/unit_tests.h" using namespace playground2; namespace { SANDBOX_TEST(SyscallIterator, Monotonous) { for (int i = 0; i < 2; ++i) { bool invalid_only = !i; // Testing both |invalid_only| cases. SyscallIterator iter(invalid_only); uint32_t next = iter.Next(); if (!invalid_only) { // The iterator should start at 0. SANDBOX_ASSERT(next == 0); } for (uint32_t last = next; !iter.Done(); last = next) { next = iter.Next(); SANDBOX_ASSERT(last < next); } // The iterator should always return 0xFFFFFFFFu as the last value. SANDBOX_ASSERT(next == 0xFFFFFFFFu); } } SANDBOX_TEST(SyscallIterator, PublicSyscallRange) { SyscallIterator iter(false); uint32_t next = iter.Next(); // The iterator should cover the public syscall range // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls. // We're assuming MIN_SYSCALL == 0 for all architectures, // this is currently valid for Intel and ARM EABI. SANDBOX_ASSERT(MIN_SYSCALL == 0); SANDBOX_ASSERT(next == MIN_SYSCALL); for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) { SANDBOX_ASSERT((next = iter.Next()) == last + 1); } SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1); } #if defined(__arm__) SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) { SyscallIterator iter(false); uint32_t next = iter.Next(); while (next < MIN_PRIVATE_SYSCALL - 1) { next = iter.Next(); } // The iterator should cover the ARM private syscall range // without skipping syscalls. SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1); for (uint32_t last = next; next < MAX_PRIVATE_SYSCALL + 1; last = next) { SANDBOX_ASSERT((next = iter.Next()) == last + 1); } SANDBOX_ASSERT(next == MAX_PRIVATE_SYSCALL + 1); } SANDBOX_TEST(SyscallIterator, ARMHiddenSyscallRange) { SyscallIterator iter(false); uint32_t next = iter.Next(); while (next < MIN_GHOST_SYSCALL - 1) { next = iter.Next(); } // The iterator should cover the ARM hidden syscall range // without skipping syscalls. SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1); for (uint32_t last = next; next < MAX_SYSCALL + 1; last = next) { SANDBOX_ASSERT((next = iter.Next()) == last + 1); } SANDBOX_ASSERT(next == MAX_SYSCALL + 1); } #endif SANDBOX_TEST(SyscallIterator, Invalid) { for (int i = 0; i < 2; ++i) { bool invalid_only = !i; // Testing both |invalid_only| cases. SyscallIterator iter(invalid_only); uint32_t next = iter.Next(); while (next < MAX_SYSCALL + 1) { next = iter.Next(); } SANDBOX_ASSERT(next == MAX_SYSCALL + 1); while (next < 0x7FFFFFFFu) { next = iter.Next(); } // The iterator should return the signed/unsigned corner cases. SANDBOX_ASSERT(next == 0x7FFFFFFFu); next = iter.Next(); SANDBOX_ASSERT(next == 0x80000000u); SANDBOX_ASSERT(!iter.Done()); next = iter.Next(); SANDBOX_ASSERT(iter.Done()); SANDBOX_ASSERT(next == 0xFFFFFFFFu); } } SANDBOX_TEST(SyscallIterator, InvalidOnly) { bool invalid_only = true; SyscallIterator iter(invalid_only); uint32_t next = iter.Next(); // We're assuming MIN_SYSCALL == 0 for all architectures, // this is currently valid for Intel and ARM EABI. // First invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|. SANDBOX_ASSERT(MIN_SYSCALL == 0); SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1); #if defined(__arm__) next = iter.Next(); // The iterator should skip until the last invalid syscall in this range. SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1); while (next <= MAX_PRIVATE_SYSCALL) { next = iter.Next(); } next = iter.Next(); // The iterator should skip until the last invalid syscall in this range. SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1); while (next <= MAX_SYSCALL) { next = iter.Next(); } SANDBOX_ASSERT(next == MAX_SYSCALL + 1); #endif } } // namespace