15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/syscall_iterator.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sandbox {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, Monotonous) {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool invalid_only = !i;  // Testing both |invalid_only| cases.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyscallIterator iter(invalid_only);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t next = iter.Next();
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!invalid_only) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The iterator should start at 0.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SANDBOX_ASSERT(next == 0);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t last = next; !iter.Done(); last = next) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SANDBOX_ASSERT(last < next);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The iterator should always return 0xFFFFFFFFu as the last value.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, PublicSyscallRange) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the public syscall range
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're assuming MIN_SYSCALL == 0 for all architectures,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is currently valid for Intel and ARM EABI.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(MIN_SYSCALL == 0);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_SYSCALL);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__arm__)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next < MIN_PRIVATE_SYSCALL - 1) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the ARM private syscall range
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without skipping syscalls.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_PRIVATE_SYSCALL + 1; last = next) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PRIVATE_SYSCALL + 1);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, ARMHiddenSyscallRange) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next < MIN_GHOST_SYSCALL - 1) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the ARM hidden syscall range
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without skipping syscalls.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_SYSCALL + 1; last = next) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, Invalid) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool invalid_only = !i;  // Testing both |invalid_only| cases.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyscallIterator iter(invalid_only);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t next = iter.Next();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (next < MAX_SYSCALL + 1) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (next < 0x7FFFFFFFu) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The iterator should return the signed/unsigned corner cases.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0x7FFFFFFFu);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0x80000000u);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(!iter.Done());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(iter.Done());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, InvalidOnly) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool invalid_only = true;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(invalid_only);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're assuming MIN_SYSCALL == 0 for all architectures,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is currently valid for Intel and ARM EABI.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(MIN_SYSCALL == 0);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__arm__)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next = iter.Next();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should skip until the last invalid syscall in this range.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next <= MAX_PRIVATE_SYSCALL) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next = iter.Next();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should skip until the last invalid syscall in this range.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next <= MAX_SYSCALL) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace sandbox
137