1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
#include "sandbox/linux/seccomp-bpf/bpf_tests.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/services/linux_syscalls.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace sandbox {
namespace {
// |pid| is the return value of a fork()-like call. This
// makes sure that if fork() succeeded the child exits
// and the parent waits for it.
void HandlePostForkReturn(pid_t pid) {
const int kChildExitCode = 1;
if (pid > 0) {
int status = 0;
PCHECK(pid == HANDLE_EINTR(waitpid(pid, &status, 0)));
CHECK(WIFEXITED(status));
CHECK_EQ(kChildExitCode, WEXITSTATUS(status));
} else if (pid == 0) {
_exit(kChildExitCode);
}
}
// Check that HandlePostForkReturn works.
TEST(BaselinePolicy, HandlePostForkReturn) {
pid_t pid = fork();
HandlePostForkReturn(pid);
}
BPF_TEST_C(BaselinePolicy, FchmodErrno, BaselinePolicy) {
int ret = fchmod(-1, 07777);
BPF_ASSERT_EQ(-1, ret);
// Without the sandbox, this would EBADF instead.
BPF_ASSERT_EQ(EPERM, errno);
}
// TODO(jln): make this work with the sanitizers.
#if !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
BPF_TEST_C(BaselinePolicy, ForkErrno, BaselinePolicy) {
errno = 0;
pid_t pid = fork();
const int fork_errno = errno;
HandlePostForkReturn(pid);
BPF_ASSERT_EQ(-1, pid);
BPF_ASSERT_EQ(EPERM, fork_errno);
}
pid_t ForkX86Glibc() {
return syscall(__NR_clone, CLONE_PARENT_SETTID | SIGCHLD);
}
BPF_TEST_C(BaselinePolicy, ForkX86Eperm, BaselinePolicy) {
errno = 0;
pid_t pid = ForkX86Glibc();
const int fork_errno = errno;
HandlePostForkReturn(pid);
BPF_ASSERT_EQ(-1, pid);
BPF_ASSERT_EQ(EPERM, fork_errno);
}
pid_t ForkARMGlibc() {
return syscall(__NR_clone,
CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD);
}
BPF_TEST_C(BaselinePolicy, ForkArmEperm, BaselinePolicy) {
errno = 0;
pid_t pid = ForkARMGlibc();
const int fork_errno = errno;
HandlePostForkReturn(pid);
BPF_ASSERT_EQ(-1, pid);
BPF_ASSERT_EQ(EPERM, fork_errno);
}
BPF_TEST_C(BaselinePolicy, CreateThread, BaselinePolicy) {
base::Thread thread("sandbox_tests");
BPF_ASSERT(thread.Start());
}
BPF_DEATH_TEST_C(BaselinePolicy,
DisallowedCloneFlagCrashes,
DEATH_MESSAGE(GetCloneErrorMessageContentForTests()),
BaselinePolicy) {
pid_t pid = syscall(__NR_clone, CLONE_THREAD | SIGCHLD);
HandlePostForkReturn(pid);
}
#endif // !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
} // namespace
} // namespace sandbox
|