blob: 08a857a2e2933ad03eb29406874f0e48bb99d5ef [file] [log] [blame]
// 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"
namespace sandbox {
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
} // namespace sandbox