Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / sandbox / linux / seccomp-bpf / bpf_tests_unittest.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sandbox/linux/seccomp-bpf/bpf_tests.h"
6
7 #include <errno.h>
8 #include <sys/ptrace.h>
9 #include <sys/syscall.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "build/build_config.h"
16 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
17 #include "sandbox/linux/services/linux_syscalls.h"
18 #include "sandbox/linux/tests/unit_tests.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace sandbox {
22
23 namespace {
24
25 ErrorCode EmptyPolicy(SandboxBPF* sandbox, int sysno, void* aux) {
26   // |aux| should always be NULL since a type was not specified as an argument
27   // to BPF_TEST.
28   BPF_ASSERT(NULL == aux);
29   if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
30     return ErrorCode(ENOSYS);
31   } else {
32     return ErrorCode(ErrorCode::ERR_ALLOWED);
33   }
34 }
35
36 BPF_TEST(BPFTest, BPFAUXIsNull, EmptyPolicy) {
37   // Check that the implicit BPF_AUX argument is NULL when we
38   // don't specify a fourth parameter to BPF_TEST.
39   BPF_ASSERT(NULL == BPF_AUX);
40 }
41
42 class FourtyTwo {
43  public:
44   static const int kMagicValue = 42;
45   FourtyTwo() : value_(kMagicValue) {}
46   int value() { return value_; }
47
48  private:
49   int value_;
50   DISALLOW_COPY_AND_ASSIGN(FourtyTwo);
51 };
52
53 ErrorCode EmptyPolicyTakesClass(SandboxBPF* sandbox,
54                                 int sysno,
55                                 FourtyTwo* fourty_two) {
56   // |aux| should point to an instance of FourtyTwo.
57   BPF_ASSERT(fourty_two);
58   BPF_ASSERT(FourtyTwo::kMagicValue == fourty_two->value());
59   if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
60     return ErrorCode(ENOSYS);
61   } else {
62     return ErrorCode(ErrorCode::ERR_ALLOWED);
63   }
64 }
65
66 BPF_TEST(BPFTest,
67          BPFAUXPointsToClass,
68          EmptyPolicyTakesClass,
69          FourtyTwo /* *BPF_AUX */) {
70   // BPF_AUX should point to an instance of FourtyTwo.
71   BPF_ASSERT(BPF_AUX);
72   BPF_ASSERT(FourtyTwo::kMagicValue == BPF_AUX->value());
73 }
74
75 void DummyTestFunction(FourtyTwo *fourty_two) {
76 }
77
78 TEST(BPFTest, BPFTesterCompatibilityDelegateLeakTest) {
79   // Don't do anything, simply gives dynamic tools an opportunity to detect
80   // leaks.
81   {
82     BPFTesterCompatibilityDelegate<FourtyTwo> simple_delegate(
83         DummyTestFunction, EmptyPolicyTakesClass);
84   }
85   {
86     // Test polymorphism.
87     scoped_ptr<BPFTesterDelegate> simple_delegate(
88         new BPFTesterCompatibilityDelegate<FourtyTwo>(DummyTestFunction,
89                                                       EmptyPolicyTakesClass));
90   }
91 }
92
93 class EnosysPtracePolicy : public SandboxBPFPolicy {
94  public:
95   EnosysPtracePolicy() {
96     my_pid_ = syscall(__NR_getpid);
97   }
98   virtual ~EnosysPtracePolicy() {
99     // Policies should be able to bind with the process on which they are
100     // created. They should never be created in a parent process.
101     BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
102   }
103
104   virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
105                                     int system_call_number) const OVERRIDE {
106     if (!SandboxBPF::IsValidSyscallNumber(system_call_number)) {
107       return ErrorCode(ENOSYS);
108     } else if (system_call_number == __NR_ptrace) {
109       // The EvaluateSyscall function should run in the process that created
110       // the current object.
111       BPF_ASSERT_EQ(my_pid_, syscall(__NR_getpid));
112       return ErrorCode(ENOSYS);
113     } else {
114       return ErrorCode(ErrorCode::ERR_ALLOWED);
115     }
116   }
117
118  private:
119   pid_t my_pid_;
120   DISALLOW_COPY_AND_ASSIGN(EnosysPtracePolicy);
121 };
122
123 class BasicBPFTesterDelegate : public BPFTesterDelegate {
124  public:
125   BasicBPFTesterDelegate() {}
126   virtual ~BasicBPFTesterDelegate() {}
127
128   virtual scoped_ptr<SandboxBPFPolicy> GetSandboxBPFPolicy() OVERRIDE {
129     return scoped_ptr<SandboxBPFPolicy>(new EnosysPtracePolicy());
130   }
131   virtual void RunTestFunction() OVERRIDE {
132     errno = 0;
133     int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL);
134     BPF_ASSERT(-1 == ret);
135     BPF_ASSERT(ENOSYS == errno);
136   }
137
138  private:
139   DISALLOW_COPY_AND_ASSIGN(BasicBPFTesterDelegate);
140 };
141
142 // This is the most powerful and complex way to create a BPF test, but it
143 // requires a full class definition (BasicBPFTesterDelegate).
144 BPF_TEST_D(BPFTest, BPFTestWithDelegateClass, BasicBPFTesterDelegate);
145
146 // This is the simplest form of BPF tests.
147 BPF_TEST_C(BPFTest, BPFTestWithInlineTest, EnosysPtracePolicy) {
148   errno = 0;
149   int ret = ptrace(PTRACE_TRACEME, -1, NULL, NULL);
150   BPF_ASSERT(-1 == ret);
151   BPF_ASSERT(ENOSYS == errno);
152 }
153
154 }  // namespace
155
156 }  // namespace sandbox