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)#ifndef SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/stat.h>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/types.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "build/build_config.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/tests/unit_tests.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A BPF_DEATH_TEST is just the same as a BPF_TEST, but it assumes that the
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// test will fail with a particular known error condition. Use the DEATH_XXX()
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// macros from unit_tests.h to specify the expected error condition.
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A BPF_DEATH_TEST is always disabled under ThreadSanitizer, see
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// crbug.com/243968.
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define BPF_DEATH_TEST(test_case_name, test_name, death, policy, aux...)      \
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void BPF_TEST_##test_name(sandbox::BpfTests<aux>::AuxType& BPF_AUX);        \
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TEST(test_case_name, DISABLE_ON_TSAN(test_name)) {                          \
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sandbox::BpfTests<aux>::TestArgs arg(BPF_TEST_##test_name, policy);       \
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sandbox::BpfTests<aux>::RunTestInProcess(                                 \
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   sandbox::BpfTests<aux>::TestWrapper, &arg, \
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   death);                                    \
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }                                                                           \
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void BPF_TEST_##test_name(sandbox::BpfTests<aux>::AuxType& BPF_AUX)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BPF_TEST() is a special version of SANDBOX_TEST(). It turns into a no-op,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the host does not have kernel support for running BPF filters.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also, it takes advantage of the Die class to avoid calling LOG(FATAL), from
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inside our tests, as we don't need or even want all the error handling that
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LOG(FATAL) would do.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BPF_TEST() takes a C++ data type as an optional fourth parameter. If
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// present, this sets up a variable that can be accessed as "BPF_AUX". This
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// variable will be passed as an argument to the "policy" function. Policies
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would typically use it as an argument to Sandbox::Trap(), if they want to
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// communicate data between the BPF_TEST() and a Trap() function.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BPF_TEST(test_case_name, test_name, policy, aux...)                   \
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BPF_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS(), policy, aux)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Assertions are handled exactly the same as with a normal SANDBOX_TEST()
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BPF_ASSERT SANDBOX_ASSERT
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The "Aux" type is optional. We use an "empty" type by default, so that if
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the caller doesn't provide any type, all the BPF_AUX related data compiles
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to nothing.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class Aux = int[0]>
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BpfTests : public UnitTests {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef Aux AuxType;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class TestArgs {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestArgs(void (*t)(AuxType&), playground2::Sandbox::EvaluateSyscall p)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : test_(t),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          policy_(p),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          aux_() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void (*test() const)(AuxType&) { return test_; }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playground2::Sandbox::EvaluateSyscall policy() const { return policy_; }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class BpfTests;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void (*test_)(AuxType&);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playground2::Sandbox::EvaluateSyscall policy_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AuxType aux_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TestWrapper(void *void_arg) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestArgs *arg = reinterpret_cast<TestArgs *>(void_arg);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    playground2::Die::EnableSimpleExit();
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (playground2::Sandbox::SupportsSeccompSandbox(-1) ==
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        playground2::Sandbox::STATUS_AVAILABLE) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ensure the the sandbox is actually available at this time
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int proc_fd;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BPF_ASSERT((proc_fd = open("/proc", O_RDONLY|O_DIRECTORY)) >= 0);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BPF_ASSERT(playground2::Sandbox::SupportsSeccompSandbox(proc_fd) ==
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 playground2::Sandbox::STATUS_AVAILABLE);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Initialize and then start the sandbox with our custom policy
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      playground2::Sandbox sandbox;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sandbox.set_proc_fd(proc_fd);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sandbox.SetSandboxPolicy(arg->policy(), &arg->aux_);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sandbox.Sandbox::StartSandbox();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      arg->test()(arg->aux_);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      printf("This BPF test is not fully running in this configuration!\n");
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // Android, ARM and Valgrind are the three only configurations where we
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // accept not having kernel BPF support.
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      // TODO(jln): remote ARM from this list when possible (crbug.com/243478).
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (!IsAndroid() && !IsRunningOnValgrind() && !IsArchitectureArm()) {
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const bool seccomp_bpf_is_supported = false;
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        BPF_ASSERT(seccomp_bpf_is_supported);
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Call the compiler and verify the policy. That's the least we can do,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // if we don't have kernel support.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      playground2::Sandbox sandbox;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sandbox.SetSandboxPolicy(arg->policy(), &arg->aux_);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      playground2::Sandbox::Program *program =
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          sandbox.AssembleFilter(true /* force_verification */);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delete program;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sandbox::UnitTests::IgnoreThisTest();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(BpfTests);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // SANDBOX_LINUX_SECCOMP_BPF_BPF_TESTS_H__
123