forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbaseline_policy_android.cc
238 lines (208 loc) · 6.92 KB
/
baseline_policy_android.cc
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// 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_android.h"
#include <errno.h>
#include <fcntl.h>
#include <linux/net.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#if defined(__x86_64__)
#include <asm/prctl.h>
#endif
using sandbox::bpf_dsl::AllOf;
using sandbox::bpf_dsl::Allow;
using sandbox::bpf_dsl::AnyOf;
using sandbox::bpf_dsl::Arg;
using sandbox::bpf_dsl::BoolExpr;
using sandbox::bpf_dsl::If;
using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::ResultExpr;
namespace sandbox {
#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC O_CLOEXEC
#endif
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK O_NONBLOCK
#endif
#define CASES SANDBOX_BPF_DSL_CASES
namespace {
#if !defined(__i386__)
// Restricts the arguments to sys_socket() to AF_UNIX. Returns a BoolExpr that
// evaluates to true if the syscall should be allowed.
BoolExpr RestrictSocketArguments(const Arg<int>& domain,
const Arg<int>& type,
const Arg<int>& protocol) {
const int kSockFlags = SOCK_CLOEXEC | SOCK_NONBLOCK;
return AllOf(domain == AF_UNIX,
AnyOf((type & ~kSockFlags) == SOCK_DGRAM,
(type & ~kSockFlags) == SOCK_STREAM),
protocol == 0);
}
#endif // !defined(__i386__)
} // namespace
BaselinePolicyAndroid::BaselinePolicyAndroid()
: BaselinePolicy() {}
BaselinePolicyAndroid::~BaselinePolicyAndroid() {}
ResultExpr BaselinePolicyAndroid::EvaluateSyscall(int sysno) const {
bool override_and_allow = false;
switch (sysno) {
// TODO(rsesek): restrict clone parameters.
case __NR_clone:
case __NR_epoll_pwait:
case __NR_fdatasync:
case __NR_flock:
case __NR_fsync:
case __NR_ftruncate:
#if defined(__i386__) || defined(__arm__) || defined(__mips32__)
case __NR_ftruncate64:
#endif
#if defined(__x86_64__) || defined(__aarch64__)
case __NR_newfstatat:
case __NR_fstatfs:
#elif defined(__i386__) || defined(__arm__) || defined(__mips32__)
case __NR_fstatat64:
case __NR_fstatfs64:
#endif
#if defined(__i386__) || defined(__arm__) || defined(__mips__)
case __NR_getdents:
#endif
case __NR_getdents64:
case __NR_getpriority:
case __NR_ioctl:
case __NR_mremap:
#if defined(__i386__)
// Used on pre-N to initialize threads in ART.
case __NR_modify_ldt:
#endif
case __NR_msync:
// File system access cannot be restricted with seccomp-bpf on Android,
// since the JVM classloader and other Framework features require file
// access. It may be possible to restrict the filesystem with SELinux.
// Currently we rely on the app/service UID isolation to create a
// filesystem "sandbox".
#if !defined(ARCH_CPU_ARM64)
case __NR_open:
#endif
case __NR_openat:
case __NR_pread64:
case __NR_pwrite64:
case __NR_rt_sigtimedwait:
case __NR_sched_getparam:
case __NR_sched_getscheduler:
case __NR_sched_setscheduler:
case __NR_setpriority:
#if defined(__i386__)
// Used on N+ instead of __NR_modify_ldt to initialize threads in ART.
case __NR_set_thread_area:
#endif
case __NR_set_tid_address:
case __NR_sigaltstack:
#if defined(__i386__) || defined(__arm__)
case __NR_ugetrlimit:
#else
case __NR_getrlimit:
#endif
case __NR_sysinfo: // https://crbug.com/655277
case __NR_uname:
// Permit socket operations so that renderers can connect to logd and
// debuggerd. The arguments to socket() are further restricted below.
// Note that on i386, both of these calls map to __NR_socketcall, which
// is demultiplexed below.
#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \
defined(__mips__)
case __NR_getsockopt:
case __NR_connect:
case __NR_socket:
#endif
// Ptrace is allowed so the Breakpad Microdumper can fork in a renderer
// and then ptrace the parent.
case __NR_ptrace:
override_and_allow = true;
break;
}
// https://crbug.com/772441 and https://crbug.com/760020.
if (SyscallSets::IsEventFd(sysno)) {
return Allow();
}
// https://crbug.com/644759
if (sysno == __NR_rt_tgsigqueueinfo) {
const Arg<pid_t> tgid(0);
return If(tgid == policy_pid(), Allow())
.Else(Error(EPERM));
}
// https://crbug.com/766245
if (sysno == __NR_process_vm_readv) {
const Arg<pid_t> pid(0);
return If(pid == policy_pid(), Allow())
.Else(Error(EPERM));
}
// https://crbug.com/655299
if (sysno == __NR_clock_getres) {
return RestrictClockID();
}
// https://crbug.com/826289
if (sysno == __NR_getrusage) {
return RestrictGetrusage();
}
#if defined(__x86_64__)
if (sysno == __NR_arch_prctl) {
const Arg<int> code(0);
return If(code == ARCH_SET_GS, Allow()).Else(Error(EPERM));
}
#endif
// Restrict socket-related operations. On non-i386 platforms, these are
// individual syscalls. On i386, the socketcall syscall demultiplexes many
// socket operations.
#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \
defined(__mips__)
if (sysno == __NR_socket) {
const Arg<int> domain(0);
const Arg<int> type(1);
const Arg<int> protocol(2);
return If(RestrictSocketArguments(domain, type, protocol), Allow())
.Else(Error(EPERM));
}
// https://crbug.com/655300
if (sysno == __NR_getsockname) {
// Rather than blocking with SIGSYS, just return an error. This is not
// documented to be a valid errno, but we will use it anyways.
return Error(EPERM);
}
// https://crbug.com/682488, https://crbug.com/701137
if (sysno == __NR_setsockopt) {
// The baseline policy applies other restrictions to setsockopt.
const Arg<int> level(1);
const Arg<int> option(2);
return If(AllOf(level == SOL_SOCKET,
AnyOf(option == SO_SNDTIMEO,
option == SO_RCVTIMEO,
option == SO_SNDBUF,
option == SO_REUSEADDR)),
Allow())
.Else(BaselinePolicy::EvaluateSyscall(sysno));
}
#elif defined(__i386__)
if (sysno == __NR_socketcall) {
// The baseline policy allows other socketcall sub-calls.
const Arg<int> socketcall(0);
return Switch(socketcall)
.CASES((SYS_CONNECT,
SYS_SOCKET,
SYS_SETSOCKOPT,
SYS_GETSOCKOPT),
Allow())
.Default(BaselinePolicy::EvaluateSyscall(sysno));
}
#endif
if (override_and_allow)
return Allow();
return BaselinePolicy::EvaluateSyscall(sysno);
}
} // namespace sandbox