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