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/syscall_iterator.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdint.h>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "sandbox/linux/seccomp-bpf/linux_seccomp.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sandbox {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, Monotonous) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool invalid_only = !i;  // Testing both |invalid_only| cases.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyscallIterator iter(invalid_only);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t next = iter.Next();
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!invalid_only) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The iterator should start at 0.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SANDBOX_ASSERT(next == 0);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (uint32_t last = next; !iter.Done(); last = next) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SANDBOX_ASSERT(last < next);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The iterator should always return 0xFFFFFFFFu as the last value.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(__mips__)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SANDBOX_TEST(SyscallIterator, PublicSyscallRangeMIPS) {
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SyscallIterator iter(false);
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t next = iter.Next();
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == 0);
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Since on MIPS MIN_SYSCALL != 0 we need to move iterator to valid range.
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  next = iter.Next();
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The iterator should cover the public syscall range
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SANDBOX_TEST(SyscallIterator, PublicSyscallRangeIntelArm) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the public syscall range
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MIN_SYSCALL..MAX_PUBLIC_SYSCALL, without skipping syscalls.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're assuming MIN_SYSCALL == 0 for all architectures,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is currently valid for Intel and ARM EABI.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(MIN_SYSCALL == 0);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_SYSCALL);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_PUBLIC_SYSCALL + 1; last = next) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // defined(__mips__)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__arm__)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, ARMPrivateSyscallRange) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next < MIN_PRIVATE_SYSCALL - 1) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the ARM private syscall range
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without skipping syscalls.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_PRIVATE_SYSCALL + 1; last = next) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PRIVATE_SYSCALL + 1);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, ARMHiddenSyscallRange) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(false);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next < MIN_GHOST_SYSCALL - 1) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should cover the ARM hidden syscall range
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without skipping syscalls.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t last = next; next < MAX_SYSCALL + 1; last = next) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT((next = iter.Next()) == last + 1);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_TEST(SyscallIterator, Invalid) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool invalid_only = !i;  // Testing both |invalid_only| cases.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyscallIterator iter(invalid_only);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t next = iter.Next();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (next < MAX_SYSCALL + 1) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (next < 0x7FFFFFFFu) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next = iter.Next();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The iterator should return the signed/unsigned corner cases.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0x7FFFFFFFu);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0x80000000u);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(!iter.Done());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(iter.Done());
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SANDBOX_ASSERT(next == 0xFFFFFFFFu);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(__mips__)
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SANDBOX_TEST(SyscallIterator, InvalidOnlyMIPS) {
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool invalid_only = true;
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SyscallIterator iter(invalid_only);
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t next = iter.Next();
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == 0);
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // For Mips O32 ABI we're assuming MIN_SYSCALL == 4000.
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(MIN_SYSCALL == 4000);
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Since on MIPS MIN_SYSCALL != 0, we need to move iterator to valid range
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // The iterator should skip until the last invalid syscall in this range.
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  next = iter.Next();
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == MIN_SYSCALL - 1);
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  next = iter.Next();
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // First next invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SANDBOX_TEST(SyscallIterator, InvalidOnlyIntelArm) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool invalid_only = true;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyscallIterator iter(invalid_only);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t next = iter.Next();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're assuming MIN_SYSCALL == 0 for all architectures,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is currently valid for Intel and ARM EABI.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First invalid syscall should then be |MAX_PUBLIC_SYSCALL + 1|.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(MIN_SYSCALL == 0);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_PUBLIC_SYSCALL + 1);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__arm__)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next = iter.Next();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should skip until the last invalid syscall in this range.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_PRIVATE_SYSCALL - 1);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next <= MAX_PRIVATE_SYSCALL) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next = iter.Next();
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The iterator should skip until the last invalid syscall in this range.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MIN_GHOST_SYSCALL - 1);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (next <= MAX_SYSCALL) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next = iter.Next();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SANDBOX_ASSERT(next == MAX_SYSCALL + 1);
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // defined(__arm__)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif  // defined(__mips__)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace sandbox
180