1*ec63e07aSXin Li // Copyright 2019 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "sandboxed_api/sandbox2/policybuilder.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <fcntl.h> // For the fcntl flags
18*ec63e07aSXin Li #include <linux/bpf_common.h>
19*ec63e07aSXin Li #include <linux/filter.h>
20*ec63e07aSXin Li #include <linux/futex.h>
21*ec63e07aSXin Li #include <linux/random.h> // For GRND_NONBLOCK
22*ec63e07aSXin Li #include <linux/seccomp.h>
23*ec63e07aSXin Li #include <stddef.h>
24*ec63e07aSXin Li #include <sys/ioctl.h>
25*ec63e07aSXin Li #include <sys/mman.h> // For mmap arguments
26*ec63e07aSXin Li #include <sys/prctl.h>
27*ec63e07aSXin Li #include <sys/socket.h>
28*ec63e07aSXin Li #include <sys/stat.h>
29*ec63e07aSXin Li #include <sys/statvfs.h>
30*ec63e07aSXin Li #include <syscall.h>
31*ec63e07aSXin Li #include <unistd.h>
32*ec63e07aSXin Li
33*ec63e07aSXin Li #include <array>
34*ec63e07aSXin Li #include <cerrno>
35*ec63e07aSXin Li #include <csignal>
36*ec63e07aSXin Li #include <cstdint>
37*ec63e07aSXin Li #include <cstdlib>
38*ec63e07aSXin Li #include <deque>
39*ec63e07aSXin Li #include <functional>
40*ec63e07aSXin Li #include <iterator>
41*ec63e07aSXin Li #include <limits>
42*ec63e07aSXin Li #include <memory>
43*ec63e07aSXin Li #include <optional>
44*ec63e07aSXin Li #include <string>
45*ec63e07aSXin Li #include <utility>
46*ec63e07aSXin Li #include <vector>
47*ec63e07aSXin Li
48*ec63e07aSXin Li #include "absl/container/flat_hash_set.h"
49*ec63e07aSXin Li #include "absl/log/log.h"
50*ec63e07aSXin Li #include "absl/memory/memory.h"
51*ec63e07aSXin Li #include "absl/status/status.h"
52*ec63e07aSXin Li #include "absl/status/statusor.h"
53*ec63e07aSXin Li #include "absl/strings/match.h"
54*ec63e07aSXin Li #include "absl/strings/str_cat.h"
55*ec63e07aSXin Li #include "absl/strings/string_view.h"
56*ec63e07aSXin Li #include "absl/types/span.h"
57*ec63e07aSXin Li #include "sandboxed_api/config.h"
58*ec63e07aSXin Li #include "sandboxed_api/sandbox2/allow_all_syscalls.h"
59*ec63e07aSXin Li #include "sandboxed_api/sandbox2/allow_unrestricted_networking.h"
60*ec63e07aSXin Li #include "sandboxed_api/sandbox2/namespace.h"
61*ec63e07aSXin Li #include "sandboxed_api/sandbox2/policy.h"
62*ec63e07aSXin Li #include "sandboxed_api/sandbox2/syscall.h"
63*ec63e07aSXin Li #include "sandboxed_api/sandbox2/trace_all_syscalls.h"
64*ec63e07aSXin Li #include "sandboxed_api/sandbox2/util/bpf_helper.h"
65*ec63e07aSXin Li #include "sandboxed_api/sandbox2/violation.pb.h"
66*ec63e07aSXin Li #include "sandboxed_api/util/path.h"
67*ec63e07aSXin Li
68*ec63e07aSXin Li #if defined(SAPI_X86_64)
69*ec63e07aSXin Li #include <asm/prctl.h>
70*ec63e07aSXin Li #elif defined(SAPI_PPC64_LE)
71*ec63e07aSXin Li #include <asm/termbits.h> // On PPC, TCGETS macro needs termios
72*ec63e07aSXin Li #endif
73*ec63e07aSXin Li
74*ec63e07aSXin Li #ifndef MAP_FIXED_NOREPLACE
75*ec63e07aSXin Li #define MAP_FIXED_NOREPLACE 0x100000
76*ec63e07aSXin Li #endif
77*ec63e07aSXin Li #ifndef PR_SET_VMA
78*ec63e07aSXin Li #define PR_SET_VMA 0x53564d41
79*ec63e07aSXin Li #endif
80*ec63e07aSXin Li #ifndef PR_SET_VMA_ANON_NAME
81*ec63e07aSXin Li #define PR_SET_VMA_ANON_NAME 0
82*ec63e07aSXin Li #endif
83*ec63e07aSXin Li
84*ec63e07aSXin Li namespace sandbox2 {
85*ec63e07aSXin Li namespace {
86*ec63e07aSXin Li
87*ec63e07aSXin Li namespace file = ::sapi::file;
88*ec63e07aSXin Li
89*ec63e07aSXin Li constexpr std::array<uint32_t, 2> kMmapSyscalls = {
90*ec63e07aSXin Li #ifdef __NR_mmap2
91*ec63e07aSXin Li __NR_mmap2,
92*ec63e07aSXin Li #endif
93*ec63e07aSXin Li #ifdef __NR_mmap
94*ec63e07aSXin Li __NR_mmap,
95*ec63e07aSXin Li #endif
96*ec63e07aSXin Li };
97*ec63e07aSXin Li
CheckBpfBounds(const sock_filter & filter,size_t max_jmp)98*ec63e07aSXin Li bool CheckBpfBounds(const sock_filter& filter, size_t max_jmp) {
99*ec63e07aSXin Li if (BPF_CLASS(filter.code) == BPF_JMP) {
100*ec63e07aSXin Li if (BPF_OP(filter.code) == BPF_JA) {
101*ec63e07aSXin Li return filter.k <= max_jmp;
102*ec63e07aSXin Li }
103*ec63e07aSXin Li return filter.jt <= max_jmp && filter.jf <= max_jmp;
104*ec63e07aSXin Li }
105*ec63e07aSXin Li return true;
106*ec63e07aSXin Li }
107*ec63e07aSXin Li
IsOnReadOnlyDev(const std::string & path)108*ec63e07aSXin Li bool IsOnReadOnlyDev(const std::string& path) {
109*ec63e07aSXin Li struct statvfs vfs;
110*ec63e07aSXin Li if (TEMP_FAILURE_RETRY(statvfs(path.c_str(), &vfs)) == -1) {
111*ec63e07aSXin Li PLOG(ERROR) << "Could not statvfs: " << path.c_str();
112*ec63e07aSXin Li return false;
113*ec63e07aSXin Li }
114*ec63e07aSXin Li return vfs.f_flag & ST_RDONLY;
115*ec63e07aSXin Li }
116*ec63e07aSXin Li
117*ec63e07aSXin Li } // namespace
118*ec63e07aSXin Li
Allow(UnrestrictedNetworking tag)119*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::Allow(UnrestrictedNetworking tag) {
120*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
121*ec63e07aSXin Li allow_unrestricted_networking_ = true;
122*ec63e07aSXin Li return *this;
123*ec63e07aSXin Li }
124*ec63e07aSXin Li
AllowSyscall(uint32_t num)125*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSyscall(uint32_t num) {
126*ec63e07aSXin Li if (handled_syscalls_.insert(num).second) {
127*ec63e07aSXin Li user_policy_.insert(user_policy_.end(), {SYSCALL(num, ALLOW)});
128*ec63e07aSXin Li }
129*ec63e07aSXin Li return *this;
130*ec63e07aSXin Li }
131*ec63e07aSXin Li
AllowSyscalls(absl::Span<const uint32_t> nums)132*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSyscalls(absl::Span<const uint32_t> nums) {
133*ec63e07aSXin Li for (auto num : nums) {
134*ec63e07aSXin Li AllowSyscall(num);
135*ec63e07aSXin Li }
136*ec63e07aSXin Li return *this;
137*ec63e07aSXin Li }
138*ec63e07aSXin Li
BlockSyscallsWithErrno(absl::Span<const uint32_t> nums,int error)139*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::BlockSyscallsWithErrno(
140*ec63e07aSXin Li absl::Span<const uint32_t> nums, int error) {
141*ec63e07aSXin Li for (auto num : nums) {
142*ec63e07aSXin Li BlockSyscallWithErrno(num, error);
143*ec63e07aSXin Li }
144*ec63e07aSXin Li return *this;
145*ec63e07aSXin Li }
146*ec63e07aSXin Li
BlockSyscallWithErrno(uint32_t num,int error)147*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(uint32_t num, int error) {
148*ec63e07aSXin Li if (handled_syscalls_.insert(num).second) {
149*ec63e07aSXin Li user_policy_.insert(user_policy_.end(), {SYSCALL(num, ERRNO(error))});
150*ec63e07aSXin Li if (num == __NR_bpf) {
151*ec63e07aSXin Li user_policy_handles_bpf_ = true;
152*ec63e07aSXin Li }
153*ec63e07aSXin Li if (num == __NR_ptrace) {
154*ec63e07aSXin Li user_policy_handles_ptrace_ = true;
155*ec63e07aSXin Li }
156*ec63e07aSXin Li }
157*ec63e07aSXin Li return *this;
158*ec63e07aSXin Li }
159*ec63e07aSXin Li
OverridableBlockSyscallWithErrno(uint32_t num,int error)160*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::OverridableBlockSyscallWithErrno(uint32_t num,
161*ec63e07aSXin Li int error) {
162*ec63e07aSXin Li overridable_policy_.insert(overridable_policy_.end(),
163*ec63e07aSXin Li {SYSCALL(num, ERRNO(error))});
164*ec63e07aSXin Li return *this;
165*ec63e07aSXin Li }
166*ec63e07aSXin Li
AllowEpollWait()167*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowEpollWait() {
168*ec63e07aSXin Li return AllowSyscalls({
169*ec63e07aSXin Li #ifdef __NR_epoll_wait
170*ec63e07aSXin Li __NR_epoll_wait,
171*ec63e07aSXin Li #endif
172*ec63e07aSXin Li #ifdef __NR_epoll_pwait
173*ec63e07aSXin Li __NR_epoll_pwait,
174*ec63e07aSXin Li #endif
175*ec63e07aSXin Li #ifdef __NR_epoll_pwait2
176*ec63e07aSXin Li __NR_epoll_pwait2,
177*ec63e07aSXin Li #endif
178*ec63e07aSXin Li });
179*ec63e07aSXin Li }
180*ec63e07aSXin Li
AllowEpoll()181*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowEpoll() {
182*ec63e07aSXin Li AllowSyscalls({
183*ec63e07aSXin Li #ifdef __NR_epoll_create
184*ec63e07aSXin Li __NR_epoll_create,
185*ec63e07aSXin Li #endif
186*ec63e07aSXin Li #ifdef __NR_epoll_create1
187*ec63e07aSXin Li __NR_epoll_create1,
188*ec63e07aSXin Li #endif
189*ec63e07aSXin Li #ifdef __NR_epoll_ctl
190*ec63e07aSXin Li __NR_epoll_ctl,
191*ec63e07aSXin Li #endif
192*ec63e07aSXin Li });
193*ec63e07aSXin Li
194*ec63e07aSXin Li return AllowEpollWait();
195*ec63e07aSXin Li }
196*ec63e07aSXin Li
AllowInotifyInit()197*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowInotifyInit() {
198*ec63e07aSXin Li return AllowSyscalls({
199*ec63e07aSXin Li #ifdef __NR_inotify_init
200*ec63e07aSXin Li __NR_inotify_init,
201*ec63e07aSXin Li #endif
202*ec63e07aSXin Li #ifdef __NR_inotify_init1
203*ec63e07aSXin Li __NR_inotify_init1,
204*ec63e07aSXin Li #endif
205*ec63e07aSXin Li });
206*ec63e07aSXin Li }
207*ec63e07aSXin Li
AllowSelect()208*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSelect() {
209*ec63e07aSXin Li return AllowSyscalls({
210*ec63e07aSXin Li #ifdef __NR_select
211*ec63e07aSXin Li __NR_select,
212*ec63e07aSXin Li #endif
213*ec63e07aSXin Li #ifdef __NR_pselect6
214*ec63e07aSXin Li __NR_pselect6,
215*ec63e07aSXin Li #endif
216*ec63e07aSXin Li });
217*ec63e07aSXin Li }
218*ec63e07aSXin Li
AllowExit()219*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowExit() {
220*ec63e07aSXin Li return AllowSyscalls({__NR_exit, __NR_exit_group});
221*ec63e07aSXin Li }
222*ec63e07aSXin Li
AllowScudoMalloc()223*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowScudoMalloc() {
224*ec63e07aSXin Li AllowTime();
225*ec63e07aSXin Li AllowSyscalls({__NR_munmap, __NR_nanosleep});
226*ec63e07aSXin Li AllowFutexOp(FUTEX_WAKE);
227*ec63e07aSXin Li AllowLimitedMadvise();
228*ec63e07aSXin Li AllowGetRandom();
229*ec63e07aSXin Li AllowGetPIDs();
230*ec63e07aSXin Li AllowWipeOnFork();
231*ec63e07aSXin Li #ifdef __NR_open
232*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_open, ENOENT);
233*ec63e07aSXin Li #endif
234*ec63e07aSXin Li #ifdef __NR_openat
235*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_openat, ENOENT);
236*ec63e07aSXin Li #endif
237*ec63e07aSXin Li
238*ec63e07aSXin Li return AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
239*ec63e07aSXin Li return {
240*ec63e07aSXin Li ARG_32(2), // prot
241*ec63e07aSXin Li JEQ32(PROT_NONE, JUMP(&labels, prot_none)),
242*ec63e07aSXin Li JNE32(PROT_READ | PROT_WRITE, JUMP(&labels, mmap_end)),
243*ec63e07aSXin Li
244*ec63e07aSXin Li // PROT_READ | PROT_WRITE
245*ec63e07aSXin Li ARG_32(3), // flags
246*ec63e07aSXin Li BPF_STMT(BPF_ALU | BPF_AND | BPF_K,
247*ec63e07aSXin Li ~uint32_t{MAP_FIXED | MAP_NORESERVE}),
248*ec63e07aSXin Li JEQ32(MAP_PRIVATE | MAP_ANONYMOUS, ALLOW),
249*ec63e07aSXin Li JUMP(&labels, mmap_end),
250*ec63e07aSXin Li
251*ec63e07aSXin Li // PROT_NONE
252*ec63e07aSXin Li LABEL(&labels, prot_none),
253*ec63e07aSXin Li ARG_32(3), // flags
254*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ALLOW),
255*ec63e07aSXin Li
256*ec63e07aSXin Li LABEL(&labels, mmap_end),
257*ec63e07aSXin Li };
258*ec63e07aSXin Li });
259*ec63e07aSXin Li }
260*ec63e07aSXin Li
AllowTcMalloc()261*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowTcMalloc() {
262*ec63e07aSXin Li AllowTime();
263*ec63e07aSXin Li AllowRestartableSequences(kRequireFastFences);
264*ec63e07aSXin Li AllowSyscalls(
265*ec63e07aSXin Li {__NR_munmap, __NR_nanosleep, __NR_brk, __NR_mincore, __NR_membarrier});
266*ec63e07aSXin Li AllowLimitedMadvise();
267*ec63e07aSXin Li AllowPrctlSetVma();
268*ec63e07aSXin Li AllowPoll();
269*ec63e07aSXin Li AllowGetPIDs();
270*ec63e07aSXin Li
271*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mprotect, {
272*ec63e07aSXin Li ARG_32(2),
273*ec63e07aSXin Li JEQ32(PROT_READ | PROT_WRITE, ALLOW),
274*ec63e07aSXin Li JEQ32(PROT_NONE, ALLOW),
275*ec63e07aSXin Li });
276*ec63e07aSXin Li
277*ec63e07aSXin Li return AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
278*ec63e07aSXin Li return {
279*ec63e07aSXin Li ARG_32(2), // prot
280*ec63e07aSXin Li JEQ32(PROT_NONE, JUMP(&labels, prot_none)),
281*ec63e07aSXin Li JNE32(PROT_READ | PROT_WRITE, JUMP(&labels, mmap_end)),
282*ec63e07aSXin Li
283*ec63e07aSXin Li // PROT_READ | PROT_WRITE
284*ec63e07aSXin Li ARG_32(3), // flags
285*ec63e07aSXin Li JNE32(MAP_ANONYMOUS | MAP_PRIVATE, JUMP(&labels, mmap_end)),
286*ec63e07aSXin Li ALLOW,
287*ec63e07aSXin Li
288*ec63e07aSXin Li // PROT_NONE
289*ec63e07aSXin Li LABEL(&labels, prot_none),
290*ec63e07aSXin Li ARG_32(3), // flags
291*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ALLOW),
292*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, ALLOW),
293*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE, ALLOW),
294*ec63e07aSXin Li
295*ec63e07aSXin Li LABEL(&labels, mmap_end),
296*ec63e07aSXin Li };
297*ec63e07aSXin Li });
298*ec63e07aSXin Li }
299*ec63e07aSXin Li
AllowSystemMalloc()300*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSystemMalloc() {
301*ec63e07aSXin Li AllowSyscalls({__NR_munmap, __NR_brk});
302*ec63e07aSXin Li AllowFutexOp(FUTEX_WAKE);
303*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mremap, {
304*ec63e07aSXin Li ARG_32(3),
305*ec63e07aSXin Li JEQ32(MREMAP_MAYMOVE, ALLOW),
306*ec63e07aSXin Li });
307*ec63e07aSXin Li return AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
308*ec63e07aSXin Li return {
309*ec63e07aSXin Li ARG_32(2), // prot
310*ec63e07aSXin Li JEQ32(PROT_NONE, JUMP(&labels, prot_none)),
311*ec63e07aSXin Li JNE32(PROT_READ | PROT_WRITE, JUMP(&labels, mmap_end)),
312*ec63e07aSXin Li
313*ec63e07aSXin Li // PROT_READ | PROT_WRITE
314*ec63e07aSXin Li ARG_32(3), // flags
315*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE, ALLOW),
316*ec63e07aSXin Li
317*ec63e07aSXin Li // PROT_NONE
318*ec63e07aSXin Li LABEL(&labels, prot_none),
319*ec63e07aSXin Li ARG_32(3), // flags
320*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ALLOW),
321*ec63e07aSXin Li
322*ec63e07aSXin Li LABEL(&labels, mmap_end),
323*ec63e07aSXin Li };
324*ec63e07aSXin Li });
325*ec63e07aSXin Li
326*ec63e07aSXin Li return *this;
327*ec63e07aSXin Li }
328*ec63e07aSXin Li
AllowLlvmSanitizers()329*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowLlvmSanitizers() {
330*ec63e07aSXin Li if constexpr (!sapi::sanitizers::IsAny()) {
331*ec63e07aSXin Li return *this;
332*ec63e07aSXin Li }
333*ec63e07aSXin Li // *san use a custom allocator that runs mmap/unmap under the hood. For
334*ec63e07aSXin Li // example:
335*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/596d534ac3524052df210be8d3c01a33b2260a42/compiler-rt/lib/asan/asan_allocator.cpp#L980
336*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/62ec4ac90738a5f2d209ed28c822223e58aaaeb7/compiler-rt/lib/sanitizer_common/sanitizer_allocator_secondary.h#L98
337*ec63e07aSXin Li AllowMmapWithoutExec();
338*ec63e07aSXin Li AllowSyscall(__NR_munmap);
339*ec63e07aSXin Li AllowSyscall(__NR_sched_yield);
340*ec63e07aSXin Li
341*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/4bbc3290a25c0dc26007912a96e0f77b2092ee56/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp#L293
342*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mprotect,
343*ec63e07aSXin Li {
344*ec63e07aSXin Li ARG_32(2),
345*ec63e07aSXin Li BPF_STMT(BPF_AND | BPF_ALU | BPF_K,
346*ec63e07aSXin Li ~uint32_t{PROT_READ | PROT_WRITE}),
347*ec63e07aSXin Li JEQ32(PROT_NONE, ALLOW),
348*ec63e07aSXin Li });
349*ec63e07aSXin Li
350*ec63e07aSXin Li AddPolicyOnSyscall(__NR_madvise, {
351*ec63e07aSXin Li ARG_32(2),
352*ec63e07aSXin Li JEQ32(MADV_DONTDUMP, ALLOW),
353*ec63e07aSXin Li JEQ32(MADV_NOHUGEPAGE, ALLOW),
354*ec63e07aSXin Li });
355*ec63e07aSXin Li // Sanitizers read from /proc. For example:
356*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/634da7a1c61ee8c173e90a841eb1f4ea03caa20b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp#L1155
357*ec63e07aSXin Li AddDirectoryIfNamespaced("/proc");
358*ec63e07aSXin Li AllowOpen();
359*ec63e07aSXin Li // Sanitizers need pid for reports. For example:
360*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/634da7a1c61ee8c173e90a841eb1f4ea03caa20b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp#L740
361*ec63e07aSXin Li AllowGetPIDs();
362*ec63e07aSXin Li // Sanitizers may try color output. For example:
363*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/87dd3d350c4ce0115b2cdf91d85ddd05ae2661aa/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp#L157
364*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_ioctl, EPERM);
365*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/9aa39481d9eb718e872993791547053a3c1f16d5/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp#L150
366*ec63e07aSXin Li // https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_getattr_np.c;h=de7edfa0928224eb8375e2fe894d6677570fbb3b;hb=HEAD#l188
367*ec63e07aSXin Li AllowSyscall(__NR_sched_getaffinity);
368*ec63e07aSXin Li // https://github.com/llvm/llvm-project/blob/02c2b472b510ff55679844c087b66e7837e13dc2/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp#L434
369*ec63e07aSXin Li #ifdef __NR_readlink
370*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
371*ec63e07aSXin Li #endif
372*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_readlinkat, ENOENT);
373*ec63e07aSXin Li if constexpr (sapi::sanitizers::IsASan()) {
374*ec63e07aSXin Li AllowSyscall(__NR_sigaltstack);
375*ec63e07aSXin Li }
376*ec63e07aSXin Li if constexpr (sapi::sanitizers::IsTSan()) {
377*ec63e07aSXin Li AllowSyscall(__NR_set_robust_list);
378*ec63e07aSXin Li }
379*ec63e07aSXin Li return *this;
380*ec63e07aSXin Li }
381*ec63e07aSXin Li
AllowLlvmCoverage()382*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowLlvmCoverage() {
383*ec63e07aSXin Li if (!sapi::IsCoverageRun()) {
384*ec63e07aSXin Li return *this;
385*ec63e07aSXin Li }
386*ec63e07aSXin Li AllowStat();
387*ec63e07aSXin Li AllowGetPIDs();
388*ec63e07aSXin Li AllowOpen();
389*ec63e07aSXin Li AllowRead();
390*ec63e07aSXin Li AllowWrite();
391*ec63e07aSXin Li AllowMkdir();
392*ec63e07aSXin Li AllowSafeFcntl();
393*ec63e07aSXin Li AllowSyscalls({
394*ec63e07aSXin Li __NR_munmap, __NR_close, __NR_lseek,
395*ec63e07aSXin Li #ifdef __NR__llseek
396*ec63e07aSXin Li __NR__llseek, // Newer glibc on PPC
397*ec63e07aSXin Li #endif
398*ec63e07aSXin Li });
399*ec63e07aSXin Li AllowTcMalloc();
400*ec63e07aSXin Li AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
401*ec63e07aSXin Li return {
402*ec63e07aSXin Li ARG_32(2), // prot
403*ec63e07aSXin Li JNE32(PROT_READ | PROT_WRITE, JUMP(&labels, mmap_end)),
404*ec63e07aSXin Li ARG_32(3), // flags
405*ec63e07aSXin Li JEQ32(MAP_SHARED, ALLOW),
406*ec63e07aSXin Li LABEL(&labels, mmap_end),
407*ec63e07aSXin Li };
408*ec63e07aSXin Li });
409*ec63e07aSXin Li AddDirectoryIfNamespaced(getenv("COVERAGE_DIR"), /*is_ro=*/false);
410*ec63e07aSXin Li return *this;
411*ec63e07aSXin Li }
412*ec63e07aSXin Li
AllowLimitedMadvise()413*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowLimitedMadvise() {
414*ec63e07aSXin Li return AddPolicyOnSyscall(__NR_madvise, {
415*ec63e07aSXin Li ARG_32(2),
416*ec63e07aSXin Li JEQ32(MADV_DONTNEED, ALLOW),
417*ec63e07aSXin Li JEQ32(MADV_REMOVE, ALLOW),
418*ec63e07aSXin Li JEQ32(MADV_HUGEPAGE, ALLOW),
419*ec63e07aSXin Li JEQ32(MADV_NOHUGEPAGE, ALLOW),
420*ec63e07aSXin Li });
421*ec63e07aSXin Li }
422*ec63e07aSXin Li
AllowMmapWithoutExec()423*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowMmapWithoutExec() {
424*ec63e07aSXin Li return AddPolicyOnMmap({
425*ec63e07aSXin Li ARG_32(2),
426*ec63e07aSXin Li BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, PROT_EXEC, 1, 0),
427*ec63e07aSXin Li ALLOW,
428*ec63e07aSXin Li });
429*ec63e07aSXin Li }
430*ec63e07aSXin Li
AllowMmap()431*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowMmap() {
432*ec63e07aSXin Li return AllowSyscalls(kMmapSyscalls);
433*ec63e07aSXin Li }
434*ec63e07aSXin Li
AllowOpen()435*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowOpen() {
436*ec63e07aSXin Li #ifdef __NR_creat
437*ec63e07aSXin Li AllowSyscall(__NR_creat);
438*ec63e07aSXin Li #endif
439*ec63e07aSXin Li #ifdef __NR_open
440*ec63e07aSXin Li AllowSyscall(__NR_open);
441*ec63e07aSXin Li #endif
442*ec63e07aSXin Li #ifdef __NR_openat
443*ec63e07aSXin Li AllowSyscall(__NR_openat);
444*ec63e07aSXin Li #endif
445*ec63e07aSXin Li return *this;
446*ec63e07aSXin Li }
447*ec63e07aSXin Li
AllowStat()448*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowStat() {
449*ec63e07aSXin Li #ifdef __NR_fstat
450*ec63e07aSXin Li AllowSyscall(__NR_fstat);
451*ec63e07aSXin Li #endif
452*ec63e07aSXin Li #ifdef __NR_fstat64
453*ec63e07aSXin Li AllowSyscall(__NR_fstat64);
454*ec63e07aSXin Li #endif
455*ec63e07aSXin Li #ifdef __NR_fstatat
456*ec63e07aSXin Li AllowSyscall(__NR_fstatat);
457*ec63e07aSXin Li #endif
458*ec63e07aSXin Li #ifdef __NR_fstatat64
459*ec63e07aSXin Li AllowSyscall(__NR_fstatat64);
460*ec63e07aSXin Li #endif
461*ec63e07aSXin Li #ifdef __NR_fstatfs
462*ec63e07aSXin Li AllowSyscall(__NR_fstatfs);
463*ec63e07aSXin Li #endif
464*ec63e07aSXin Li #ifdef __NR_fstatfs64
465*ec63e07aSXin Li AllowSyscall(__NR_fstatfs64);
466*ec63e07aSXin Li #endif
467*ec63e07aSXin Li #ifdef __NR_lstat
468*ec63e07aSXin Li AllowSyscall(__NR_lstat);
469*ec63e07aSXin Li #endif
470*ec63e07aSXin Li #ifdef __NR_lstat64
471*ec63e07aSXin Li AllowSyscall(__NR_lstat64);
472*ec63e07aSXin Li #endif
473*ec63e07aSXin Li #ifdef __NR_newfstatat
474*ec63e07aSXin Li AllowSyscall(__NR_newfstatat);
475*ec63e07aSXin Li #endif
476*ec63e07aSXin Li #ifdef __NR_oldfstat
477*ec63e07aSXin Li AllowSyscall(__NR_oldfstat);
478*ec63e07aSXin Li #endif
479*ec63e07aSXin Li #ifdef __NR_oldlstat
480*ec63e07aSXin Li AllowSyscall(__NR_oldlstat);
481*ec63e07aSXin Li #endif
482*ec63e07aSXin Li #ifdef __NR_oldstat
483*ec63e07aSXin Li AllowSyscall(__NR_oldstat);
484*ec63e07aSXin Li #endif
485*ec63e07aSXin Li #ifdef __NR_stat
486*ec63e07aSXin Li AllowSyscall(__NR_stat);
487*ec63e07aSXin Li #endif
488*ec63e07aSXin Li #ifdef __NR_stat64
489*ec63e07aSXin Li AllowSyscall(__NR_stat64);
490*ec63e07aSXin Li #endif
491*ec63e07aSXin Li #ifdef __NR_statfs
492*ec63e07aSXin Li AllowSyscall(__NR_statfs);
493*ec63e07aSXin Li #endif
494*ec63e07aSXin Li #ifdef __NR_statfs64
495*ec63e07aSXin Li AllowSyscall(__NR_statfs64);
496*ec63e07aSXin Li #endif
497*ec63e07aSXin Li return *this;
498*ec63e07aSXin Li }
499*ec63e07aSXin Li
AllowAccess()500*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowAccess() {
501*ec63e07aSXin Li #ifdef __NR_access
502*ec63e07aSXin Li AllowSyscall(__NR_access);
503*ec63e07aSXin Li #endif
504*ec63e07aSXin Li #ifdef __NR_faccessat
505*ec63e07aSXin Li AllowSyscall(__NR_faccessat);
506*ec63e07aSXin Li #endif
507*ec63e07aSXin Li #ifdef __NR_faccessat2
508*ec63e07aSXin Li AllowSyscall(__NR_faccessat2);
509*ec63e07aSXin Li #endif
510*ec63e07aSXin Li return *this;
511*ec63e07aSXin Li }
512*ec63e07aSXin Li
AllowDup()513*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowDup() {
514*ec63e07aSXin Li AllowSyscall(__NR_dup);
515*ec63e07aSXin Li #ifdef __NR_dup2
516*ec63e07aSXin Li AllowSyscall(__NR_dup2);
517*ec63e07aSXin Li #endif
518*ec63e07aSXin Li AllowSyscall(__NR_dup3);
519*ec63e07aSXin Li return *this;
520*ec63e07aSXin Li }
521*ec63e07aSXin Li
AllowPipe()522*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowPipe() {
523*ec63e07aSXin Li #ifdef __NR_pipe
524*ec63e07aSXin Li AllowSyscall(__NR_pipe);
525*ec63e07aSXin Li #endif
526*ec63e07aSXin Li AllowSyscall(__NR_pipe2);
527*ec63e07aSXin Li return *this;
528*ec63e07aSXin Li }
529*ec63e07aSXin Li
AllowChmod()530*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowChmod() {
531*ec63e07aSXin Li #ifdef __NR_chmod
532*ec63e07aSXin Li AllowSyscall(__NR_chmod);
533*ec63e07aSXin Li #endif
534*ec63e07aSXin Li AllowSyscall(__NR_fchmod);
535*ec63e07aSXin Li AllowSyscall(__NR_fchmodat);
536*ec63e07aSXin Li return *this;
537*ec63e07aSXin Li }
538*ec63e07aSXin Li
AllowChown()539*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowChown() {
540*ec63e07aSXin Li #ifdef __NR_chown
541*ec63e07aSXin Li AllowSyscall(__NR_chown);
542*ec63e07aSXin Li #endif
543*ec63e07aSXin Li #ifdef __NR_lchown
544*ec63e07aSXin Li AllowSyscall(__NR_lchown);
545*ec63e07aSXin Li #endif
546*ec63e07aSXin Li AllowSyscall(__NR_fchown);
547*ec63e07aSXin Li AllowSyscall(__NR_fchownat);
548*ec63e07aSXin Li return *this;
549*ec63e07aSXin Li }
550*ec63e07aSXin Li
AllowRead()551*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowRead() {
552*ec63e07aSXin Li return AllowSyscalls({
553*ec63e07aSXin Li __NR_read,
554*ec63e07aSXin Li __NR_readv,
555*ec63e07aSXin Li __NR_preadv,
556*ec63e07aSXin Li __NR_pread64,
557*ec63e07aSXin Li });
558*ec63e07aSXin Li }
559*ec63e07aSXin Li
AllowWrite()560*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowWrite() {
561*ec63e07aSXin Li return AllowSyscalls({
562*ec63e07aSXin Li __NR_write,
563*ec63e07aSXin Li __NR_writev,
564*ec63e07aSXin Li __NR_pwritev,
565*ec63e07aSXin Li __NR_pwrite64,
566*ec63e07aSXin Li });
567*ec63e07aSXin Li }
568*ec63e07aSXin Li
AllowReaddir()569*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowReaddir() {
570*ec63e07aSXin Li return AllowSyscalls({
571*ec63e07aSXin Li #ifdef __NR_getdents
572*ec63e07aSXin Li __NR_getdents,
573*ec63e07aSXin Li #endif
574*ec63e07aSXin Li #ifdef __NR_getdents64
575*ec63e07aSXin Li __NR_getdents64,
576*ec63e07aSXin Li #endif
577*ec63e07aSXin Li });
578*ec63e07aSXin Li }
579*ec63e07aSXin Li
AllowReadlink()580*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowReadlink() {
581*ec63e07aSXin Li return AllowSyscalls({
582*ec63e07aSXin Li #ifdef __NR_readlink
583*ec63e07aSXin Li __NR_readlink,
584*ec63e07aSXin Li #endif
585*ec63e07aSXin Li #ifdef __NR_readlinkat
586*ec63e07aSXin Li __NR_readlinkat,
587*ec63e07aSXin Li #endif
588*ec63e07aSXin Li });
589*ec63e07aSXin Li }
590*ec63e07aSXin Li
AllowLink()591*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowLink() {
592*ec63e07aSXin Li return AllowSyscalls({
593*ec63e07aSXin Li #ifdef __NR_link
594*ec63e07aSXin Li __NR_link,
595*ec63e07aSXin Li #endif
596*ec63e07aSXin Li #ifdef __NR_linkat
597*ec63e07aSXin Li __NR_linkat,
598*ec63e07aSXin Li #endif
599*ec63e07aSXin Li });
600*ec63e07aSXin Li }
601*ec63e07aSXin Li
AllowSymlink()602*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSymlink() {
603*ec63e07aSXin Li return AllowSyscalls({
604*ec63e07aSXin Li #ifdef __NR_symlink
605*ec63e07aSXin Li __NR_symlink,
606*ec63e07aSXin Li #endif
607*ec63e07aSXin Li #ifdef __NR_symlinkat
608*ec63e07aSXin Li __NR_symlinkat,
609*ec63e07aSXin Li #endif
610*ec63e07aSXin Li });
611*ec63e07aSXin Li }
612*ec63e07aSXin Li
AllowMkdir()613*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowMkdir() {
614*ec63e07aSXin Li return AllowSyscalls({
615*ec63e07aSXin Li #ifdef __NR_mkdir
616*ec63e07aSXin Li __NR_mkdir,
617*ec63e07aSXin Li #endif
618*ec63e07aSXin Li #ifdef __NR_mkdirat
619*ec63e07aSXin Li __NR_mkdirat,
620*ec63e07aSXin Li #endif
621*ec63e07aSXin Li });
622*ec63e07aSXin Li }
623*ec63e07aSXin Li
AllowUtime()624*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowUtime() {
625*ec63e07aSXin Li return AllowSyscalls({
626*ec63e07aSXin Li #ifdef __NR_futimens
627*ec63e07aSXin Li __NR_futimens,
628*ec63e07aSXin Li #endif
629*ec63e07aSXin Li #ifdef __NR_utime
630*ec63e07aSXin Li __NR_utime,
631*ec63e07aSXin Li #endif
632*ec63e07aSXin Li #ifdef __NR_utimes
633*ec63e07aSXin Li __NR_utimes,
634*ec63e07aSXin Li #endif
635*ec63e07aSXin Li #ifdef __NR_utimensat
636*ec63e07aSXin Li __NR_utimensat,
637*ec63e07aSXin Li #endif
638*ec63e07aSXin Li });
639*ec63e07aSXin Li }
640*ec63e07aSXin Li
AllowSafeFcntl()641*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSafeFcntl() {
642*ec63e07aSXin Li return AddPolicyOnSyscalls({__NR_fcntl,
643*ec63e07aSXin Li #ifdef __NR_fcntl64
644*ec63e07aSXin Li __NR_fcntl64
645*ec63e07aSXin Li #endif
646*ec63e07aSXin Li },
647*ec63e07aSXin Li {
648*ec63e07aSXin Li ARG_32(1),
649*ec63e07aSXin Li JEQ32(F_GETFD, ALLOW),
650*ec63e07aSXin Li JEQ32(F_SETFD, ALLOW),
651*ec63e07aSXin Li JEQ32(F_GETFL, ALLOW),
652*ec63e07aSXin Li JEQ32(F_SETFL, ALLOW),
653*ec63e07aSXin Li JEQ32(F_GETLK, ALLOW),
654*ec63e07aSXin Li JEQ32(F_SETLK, ALLOW),
655*ec63e07aSXin Li JEQ32(F_SETLKW, ALLOW),
656*ec63e07aSXin Li JEQ32(F_DUPFD, ALLOW),
657*ec63e07aSXin Li JEQ32(F_DUPFD_CLOEXEC, ALLOW),
658*ec63e07aSXin Li });
659*ec63e07aSXin Li }
660*ec63e07aSXin Li
AllowFork()661*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowFork() {
662*ec63e07aSXin Li return AllowSyscalls({
663*ec63e07aSXin Li #ifdef __NR_fork
664*ec63e07aSXin Li __NR_fork,
665*ec63e07aSXin Li #endif
666*ec63e07aSXin Li #ifdef __NR_vfork
667*ec63e07aSXin Li __NR_vfork,
668*ec63e07aSXin Li #endif
669*ec63e07aSXin Li __NR_clone});
670*ec63e07aSXin Li }
671*ec63e07aSXin Li
AllowWait()672*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowWait() {
673*ec63e07aSXin Li return AllowSyscalls({
674*ec63e07aSXin Li #ifdef __NR_waitpid
675*ec63e07aSXin Li __NR_waitpid,
676*ec63e07aSXin Li #endif
677*ec63e07aSXin Li __NR_wait4});
678*ec63e07aSXin Li }
679*ec63e07aSXin Li
AllowAlarm()680*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowAlarm() {
681*ec63e07aSXin Li return AllowSyscalls({
682*ec63e07aSXin Li #ifdef __NR_alarm
683*ec63e07aSXin Li __NR_alarm,
684*ec63e07aSXin Li #endif
685*ec63e07aSXin Li __NR_setitimer});
686*ec63e07aSXin Li }
687*ec63e07aSXin Li
AllowHandleSignals()688*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowHandleSignals() {
689*ec63e07aSXin Li return AllowSyscalls({
690*ec63e07aSXin Li __NR_rt_sigaction,
691*ec63e07aSXin Li __NR_rt_sigreturn,
692*ec63e07aSXin Li __NR_rt_sigprocmask,
693*ec63e07aSXin Li #ifdef __NR_signal
694*ec63e07aSXin Li __NR_signal,
695*ec63e07aSXin Li #endif
696*ec63e07aSXin Li #ifdef __NR_sigaction
697*ec63e07aSXin Li __NR_sigaction,
698*ec63e07aSXin Li #endif
699*ec63e07aSXin Li #ifdef __NR_sigreturn
700*ec63e07aSXin Li __NR_sigreturn,
701*ec63e07aSXin Li #endif
702*ec63e07aSXin Li #ifdef __NR_sigprocmask
703*ec63e07aSXin Li __NR_sigprocmask,
704*ec63e07aSXin Li #endif
705*ec63e07aSXin Li #ifdef __NR_sigaltstack
706*ec63e07aSXin Li __NR_sigaltstack,
707*ec63e07aSXin Li #endif
708*ec63e07aSXin Li });
709*ec63e07aSXin Li }
710*ec63e07aSXin Li
AllowTCGETS()711*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowTCGETS() {
712*ec63e07aSXin Li return AddPolicyOnSyscall(__NR_ioctl, {
713*ec63e07aSXin Li ARG_32(1),
714*ec63e07aSXin Li JEQ32(TCGETS, ALLOW),
715*ec63e07aSXin Li });
716*ec63e07aSXin Li }
717*ec63e07aSXin Li
AllowTime()718*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowTime() {
719*ec63e07aSXin Li return AllowSyscalls({
720*ec63e07aSXin Li #ifdef __NR_time
721*ec63e07aSXin Li __NR_time,
722*ec63e07aSXin Li #endif
723*ec63e07aSXin Li __NR_gettimeofday, __NR_clock_gettime});
724*ec63e07aSXin Li }
725*ec63e07aSXin Li
AllowSleep()726*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSleep() {
727*ec63e07aSXin Li return AllowSyscalls({
728*ec63e07aSXin Li __NR_clock_nanosleep,
729*ec63e07aSXin Li __NR_nanosleep,
730*ec63e07aSXin Li });
731*ec63e07aSXin Li }
732*ec63e07aSXin Li
AllowGetIDs()733*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowGetIDs() {
734*ec63e07aSXin Li return AllowSyscalls({
735*ec63e07aSXin Li __NR_getuid,
736*ec63e07aSXin Li __NR_geteuid,
737*ec63e07aSXin Li __NR_getresuid,
738*ec63e07aSXin Li __NR_getgid,
739*ec63e07aSXin Li __NR_getegid,
740*ec63e07aSXin Li __NR_getresgid,
741*ec63e07aSXin Li #ifdef __NR_getuid32
742*ec63e07aSXin Li __NR_getuid32,
743*ec63e07aSXin Li __NR_geteuid32,
744*ec63e07aSXin Li __NR_getresuid32,
745*ec63e07aSXin Li __NR_getgid32,
746*ec63e07aSXin Li __NR_getegid32,
747*ec63e07aSXin Li __NR_getresgid32,
748*ec63e07aSXin Li #endif
749*ec63e07aSXin Li __NR_getgroups,
750*ec63e07aSXin Li });
751*ec63e07aSXin Li }
752*ec63e07aSXin Li
AllowRestartableSequences(CpuFenceMode cpu_fence_mode)753*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowRestartableSequences(
754*ec63e07aSXin Li CpuFenceMode cpu_fence_mode) {
755*ec63e07aSXin Li #ifdef __NR_rseq
756*ec63e07aSXin Li AllowSyscall(__NR_rseq);
757*ec63e07aSXin Li #endif
758*ec63e07aSXin Li AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
759*ec63e07aSXin Li return {
760*ec63e07aSXin Li ARG_32(2), // prot
761*ec63e07aSXin Li JNE32(PROT_READ | PROT_WRITE, JUMP(&labels, mmap_end)),
762*ec63e07aSXin Li
763*ec63e07aSXin Li ARG_32(3), // flags
764*ec63e07aSXin Li JNE32(MAP_PRIVATE | MAP_ANONYMOUS, JUMP(&labels, mmap_end)),
765*ec63e07aSXin Li
766*ec63e07aSXin Li ALLOW,
767*ec63e07aSXin Li LABEL(&labels, mmap_end),
768*ec63e07aSXin Li };
769*ec63e07aSXin Li });
770*ec63e07aSXin Li AllowSyscall(__NR_getcpu);
771*ec63e07aSXin Li AllowSyscall(__NR_membarrier);
772*ec63e07aSXin Li AllowFutexOp(FUTEX_WAIT);
773*ec63e07aSXin Li AllowFutexOp(FUTEX_WAKE);
774*ec63e07aSXin Li AllowRead();
775*ec63e07aSXin Li AllowOpen();
776*ec63e07aSXin Li AllowPoll();
777*ec63e07aSXin Li AllowSyscall(__NR_close);
778*ec63e07aSXin Li AddPolicyOnSyscall(__NR_rt_sigprocmask, {
779*ec63e07aSXin Li ARG_32(0),
780*ec63e07aSXin Li JEQ32(SIG_SETMASK, ALLOW),
781*ec63e07aSXin Li });
782*ec63e07aSXin Li AllowPrctlSetVma();
783*ec63e07aSXin Li if (cpu_fence_mode == kAllowSlowFences) {
784*ec63e07aSXin Li AllowSyscall(__NR_sched_getaffinity);
785*ec63e07aSXin Li AllowSyscall(__NR_sched_setaffinity);
786*ec63e07aSXin Li }
787*ec63e07aSXin Li AddFileIfNamespaced("/proc/cpuinfo");
788*ec63e07aSXin Li AddFileIfNamespaced("/proc/stat");
789*ec63e07aSXin Li AddDirectoryIfNamespaced("/sys/devices/system/cpu");
790*ec63e07aSXin Li if (cpu_fence_mode == kAllowSlowFences) {
791*ec63e07aSXin Li AddFileIfNamespaced("/proc/self/cpuset");
792*ec63e07aSXin Li }
793*ec63e07aSXin Li return *this;
794*ec63e07aSXin Li }
795*ec63e07aSXin Li
AllowGetPIDs()796*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowGetPIDs() {
797*ec63e07aSXin Li return AllowSyscalls({
798*ec63e07aSXin Li __NR_getpid,
799*ec63e07aSXin Li __NR_getppid,
800*ec63e07aSXin Li __NR_gettid,
801*ec63e07aSXin Li });
802*ec63e07aSXin Li }
803*ec63e07aSXin Li
AllowGetPGIDs()804*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowGetPGIDs() {
805*ec63e07aSXin Li return AllowSyscalls({
806*ec63e07aSXin Li __NR_getpgid,
807*ec63e07aSXin Li #ifdef __NR_getpgrp
808*ec63e07aSXin Li __NR_getpgrp,
809*ec63e07aSXin Li #endif
810*ec63e07aSXin Li });
811*ec63e07aSXin Li }
812*ec63e07aSXin Li
AllowGetRlimit()813*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowGetRlimit() {
814*ec63e07aSXin Li #ifdef __NR_prlimit64
815*ec63e07aSXin Li AddPolicyOnSyscall(__NR_prlimit64, {ARG(2), JEQ64(0, 0, ALLOW)});
816*ec63e07aSXin Li #endif
817*ec63e07aSXin Li return AllowSyscalls({
818*ec63e07aSXin Li #ifdef __NR_getrlimit
819*ec63e07aSXin Li __NR_getrlimit,
820*ec63e07aSXin Li #endif
821*ec63e07aSXin Li #ifdef __NR_ugetrlimit
822*ec63e07aSXin Li __NR_ugetrlimit,
823*ec63e07aSXin Li #endif
824*ec63e07aSXin Li });
825*ec63e07aSXin Li }
826*ec63e07aSXin Li
AllowSetRlimit()827*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowSetRlimit() {
828*ec63e07aSXin Li return AllowSyscalls({
829*ec63e07aSXin Li #ifdef __NR_prlimit64
830*ec63e07aSXin Li __NR_prlimit64,
831*ec63e07aSXin Li #endif
832*ec63e07aSXin Li #ifdef __NR_setrlimit
833*ec63e07aSXin Li __NR_setrlimit,
834*ec63e07aSXin Li #endif
835*ec63e07aSXin Li #ifdef __NR_usetrlimit
836*ec63e07aSXin Li __NR_usetrlimit,
837*ec63e07aSXin Li #endif
838*ec63e07aSXin Li });
839*ec63e07aSXin Li }
840*ec63e07aSXin Li
AllowGetRandom()841*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowGetRandom() {
842*ec63e07aSXin Li return AddPolicyOnSyscall(__NR_getrandom, {
843*ec63e07aSXin Li ARG_32(2),
844*ec63e07aSXin Li JEQ32(0, ALLOW),
845*ec63e07aSXin Li JEQ32(GRND_NONBLOCK, ALLOW),
846*ec63e07aSXin Li });
847*ec63e07aSXin Li }
848*ec63e07aSXin Li
AllowWipeOnFork()849*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowWipeOnFork() {
850*ec63e07aSXin Li // System headers may not be recent enough to include MADV_WIPEONFORK.
851*ec63e07aSXin Li static constexpr uint32_t kMadv_WipeOnFork = 18;
852*ec63e07aSXin Li // The -1 value is used by code to probe that the kernel returns -EINVAL for
853*ec63e07aSXin Li // unknown values because some environments, like qemu, ignore madvise
854*ec63e07aSXin Li // completely, but code needs to know whether WIPEONFORK took effect.
855*ec63e07aSXin Li return AddPolicyOnSyscall(__NR_madvise,
856*ec63e07aSXin Li {
857*ec63e07aSXin Li ARG_32(2),
858*ec63e07aSXin Li JEQ32(kMadv_WipeOnFork, ALLOW),
859*ec63e07aSXin Li JEQ32(static_cast<uint32_t>(-1), ALLOW),
860*ec63e07aSXin Li });
861*ec63e07aSXin Li }
862*ec63e07aSXin Li
AllowLogForwarding()863*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowLogForwarding() {
864*ec63e07aSXin Li AllowWrite();
865*ec63e07aSXin Li AllowSystemMalloc();
866*ec63e07aSXin Li AllowTcMalloc();
867*ec63e07aSXin Li
868*ec63e07aSXin Li // From comms
869*ec63e07aSXin Li AllowGetPIDs();
870*ec63e07aSXin Li AllowSyscalls({// from logging code
871*ec63e07aSXin Li __NR_clock_gettime,
872*ec63e07aSXin Li // From comms
873*ec63e07aSXin Li __NR_gettid, __NR_close});
874*ec63e07aSXin Li
875*ec63e07aSXin Li // For generating stacktraces in logging (e.g. `LOG(FATAL)`)
876*ec63e07aSXin Li AddPolicyOnSyscall(__NR_rt_sigprocmask, {
877*ec63e07aSXin Li ARG_32(0),
878*ec63e07aSXin Li JEQ32(SIG_BLOCK, ALLOW),
879*ec63e07aSXin Li });
880*ec63e07aSXin Li AllowGetRlimit();
881*ec63e07aSXin Li
882*ec63e07aSXin Li // For LOG(FATAL)
883*ec63e07aSXin Li return AddPolicyOnSyscall(__NR_kill,
884*ec63e07aSXin Li [](bpf_labels& labels) -> std::vector<sock_filter> {
885*ec63e07aSXin Li return {
886*ec63e07aSXin Li ARG_32(0),
887*ec63e07aSXin Li JNE32(0, JUMP(&labels, pid_not_null)),
888*ec63e07aSXin Li ARG_32(1),
889*ec63e07aSXin Li JEQ32(SIGABRT, ALLOW),
890*ec63e07aSXin Li LABEL(&labels, pid_not_null),
891*ec63e07aSXin Li };
892*ec63e07aSXin Li });
893*ec63e07aSXin Li }
894*ec63e07aSXin Li
AllowUnlink()895*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowUnlink() {
896*ec63e07aSXin Li AllowSyscalls({
897*ec63e07aSXin Li #ifdef __NR_rmdir
898*ec63e07aSXin Li __NR_rmdir,
899*ec63e07aSXin Li #endif
900*ec63e07aSXin Li #ifdef __NR_unlink
901*ec63e07aSXin Li __NR_unlink,
902*ec63e07aSXin Li #endif
903*ec63e07aSXin Li __NR_unlinkat,
904*ec63e07aSXin Li });
905*ec63e07aSXin Li return *this;
906*ec63e07aSXin Li }
907*ec63e07aSXin Li
AllowPoll()908*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowPoll() {
909*ec63e07aSXin Li AllowSyscalls({
910*ec63e07aSXin Li #ifdef __NR_poll
911*ec63e07aSXin Li __NR_poll,
912*ec63e07aSXin Li #endif
913*ec63e07aSXin Li __NR_ppoll,
914*ec63e07aSXin Li });
915*ec63e07aSXin Li return *this;
916*ec63e07aSXin Li }
917*ec63e07aSXin Li
AllowRename()918*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowRename() {
919*ec63e07aSXin Li AllowSyscalls({
920*ec63e07aSXin Li #ifdef __NR_rename
921*ec63e07aSXin Li __NR_rename,
922*ec63e07aSXin Li #endif
923*ec63e07aSXin Li __NR_renameat,
924*ec63e07aSXin Li #ifdef __NR_renameat2
925*ec63e07aSXin Li __NR_renameat2,
926*ec63e07aSXin Li #endif
927*ec63e07aSXin Li });
928*ec63e07aSXin Li return *this;
929*ec63e07aSXin Li }
930*ec63e07aSXin Li
AllowEventFd()931*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowEventFd() {
932*ec63e07aSXin Li AllowSyscalls({
933*ec63e07aSXin Li #ifdef __NR_eventfd
934*ec63e07aSXin Li __NR_eventfd,
935*ec63e07aSXin Li #endif
936*ec63e07aSXin Li __NR_eventfd2,
937*ec63e07aSXin Li });
938*ec63e07aSXin Li return *this;
939*ec63e07aSXin Li }
940*ec63e07aSXin Li
AllowPrctlSetName()941*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowPrctlSetName() {
942*ec63e07aSXin Li AddPolicyOnSyscall(__NR_prctl, {ARG_32(0), JEQ32(PR_SET_NAME, ALLOW)});
943*ec63e07aSXin Li return *this;
944*ec63e07aSXin Li }
945*ec63e07aSXin Li
AllowPrctlSetVma()946*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowPrctlSetVma() {
947*ec63e07aSXin Li AddPolicyOnSyscall(__NR_prctl,
948*ec63e07aSXin Li [](bpf_labels& labels) -> std::vector<sock_filter> {
949*ec63e07aSXin Li return {
950*ec63e07aSXin Li ARG_32(0),
951*ec63e07aSXin Li JNE32(PR_SET_VMA, JUMP(&labels, prctlsetvma_end)),
952*ec63e07aSXin Li ARG_32(1),
953*ec63e07aSXin Li JEQ32(PR_SET_VMA_ANON_NAME, ALLOW),
954*ec63e07aSXin Li LABEL(&labels, prctlsetvma_end),
955*ec63e07aSXin Li };
956*ec63e07aSXin Li });
957*ec63e07aSXin Li return *this;
958*ec63e07aSXin Li }
959*ec63e07aSXin Li
AllowFutexOp(int op)960*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowFutexOp(int op) {
961*ec63e07aSXin Li return AddPolicyOnSyscall(
962*ec63e07aSXin Li __NR_futex, {
963*ec63e07aSXin Li ARG_32(1),
964*ec63e07aSXin Li // a <- a & FUTEX_CMD_MASK
965*ec63e07aSXin Li BPF_STMT(BPF_ALU + BPF_AND + BPF_K,
966*ec63e07aSXin Li static_cast<uint32_t>(FUTEX_CMD_MASK)),
967*ec63e07aSXin Li JEQ32(static_cast<uint32_t>(op) & FUTEX_CMD_MASK, ALLOW),
968*ec63e07aSXin Li });
969*ec63e07aSXin Li }
970*ec63e07aSXin Li
AllowStaticStartup()971*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowStaticStartup() {
972*ec63e07aSXin Li AllowGetRlimit();
973*ec63e07aSXin Li AllowSyscalls({
974*ec63e07aSXin Li // These syscalls take a pointer, so no restriction.
975*ec63e07aSXin Li __NR_uname, __NR_brk, __NR_set_tid_address,
976*ec63e07aSXin Li
977*ec63e07aSXin Li #if defined(__ARM_NR_set_tls)
978*ec63e07aSXin Li // libc sets the TLS during startup
979*ec63e07aSXin Li __ARM_NR_set_tls,
980*ec63e07aSXin Li #endif
981*ec63e07aSXin Li
982*ec63e07aSXin Li // This syscall takes a pointer and a length.
983*ec63e07aSXin Li // We could restrict length, but it might change, so not worth it.
984*ec63e07aSXin Li __NR_set_robust_list,
985*ec63e07aSXin Li });
986*ec63e07aSXin Li
987*ec63e07aSXin Li AllowFutexOp(FUTEX_WAIT_BITSET);
988*ec63e07aSXin Li
989*ec63e07aSXin Li AddPolicyOnSyscall(__NR_rt_sigaction,
990*ec63e07aSXin Li {
991*ec63e07aSXin Li ARG_32(0),
992*ec63e07aSXin Li // This is real-time signals used internally by libc.
993*ec63e07aSXin Li JEQ32(__SIGRTMIN + 0, ALLOW),
994*ec63e07aSXin Li JEQ32(__SIGRTMIN + 1, ALLOW),
995*ec63e07aSXin Li });
996*ec63e07aSXin Li
997*ec63e07aSXin Li AllowSyscall(__NR_rt_sigprocmask);
998*ec63e07aSXin Li
999*ec63e07aSXin Li #ifdef SAPI_X86_64
1000*ec63e07aSXin Li // The second argument is a pointer.
1001*ec63e07aSXin Li AddPolicyOnSyscall(__NR_arch_prctl, {
1002*ec63e07aSXin Li ARG_32(0),
1003*ec63e07aSXin Li JEQ32(ARCH_SET_FS, ALLOW),
1004*ec63e07aSXin Li });
1005*ec63e07aSXin Li #endif
1006*ec63e07aSXin Li
1007*ec63e07aSXin Li if constexpr (sapi::host_cpu::IsArm64()) {
1008*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_readlinkat, ENOENT);
1009*ec63e07aSXin Li }
1010*ec63e07aSXin Li #ifdef __NR_readlink
1011*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_readlink, ENOENT);
1012*ec63e07aSXin Li #endif
1013*ec63e07aSXin Li
1014*ec63e07aSXin Li AllowGetRlimit();
1015*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mprotect, {
1016*ec63e07aSXin Li ARG_32(2),
1017*ec63e07aSXin Li JEQ32(PROT_READ, ALLOW),
1018*ec63e07aSXin Li });
1019*ec63e07aSXin Li
1020*ec63e07aSXin Li OverridableBlockSyscallWithErrno(__NR_sigaltstack, ENOSYS);
1021*ec63e07aSXin Li
1022*ec63e07aSXin Li return *this;
1023*ec63e07aSXin Li }
1024*ec63e07aSXin Li
AllowDynamicStartup()1025*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowDynamicStartup() {
1026*ec63e07aSXin Li #ifdef __ANDROID__
1027*ec63e07aSXin Li AllowSafeFcntl();
1028*ec63e07aSXin Li AllowGetIDs();
1029*ec63e07aSXin Li AllowGetPIDs();
1030*ec63e07aSXin Li AllowGetRandom();
1031*ec63e07aSXin Li AllowSyscalls({
1032*ec63e07aSXin Li #ifdef __NR_fstatfs
1033*ec63e07aSXin Li __NR_fstatfs,
1034*ec63e07aSXin Li #endif
1035*ec63e07aSXin Li #ifdef __NR_fstatfs64
1036*ec63e07aSXin Li __NR_fstatfs64,
1037*ec63e07aSXin Li #endif
1038*ec63e07aSXin Li __NR_readlinkat,
1039*ec63e07aSXin Li __NR_sched_getaffinity,
1040*ec63e07aSXin Li __NR_sched_getscheduler,
1041*ec63e07aSXin Li });
1042*ec63e07aSXin Li AllowHandleSignals();
1043*ec63e07aSXin Li AllowFutexOp(FUTEX_WAKE_PRIVATE);
1044*ec63e07aSXin Li AddPolicyOnSyscall(__NR_prctl,
1045*ec63e07aSXin Li [](bpf_labels& labels) -> std::vector<sock_filter> {
1046*ec63e07aSXin Li return {
1047*ec63e07aSXin Li ARG_32(0), // option
1048*ec63e07aSXin Li JEQ32(PR_GET_DUMPABLE, ALLOW),
1049*ec63e07aSXin Li JNE32(PR_SET_VMA, JUMP(&labels, prctl_end)),
1050*ec63e07aSXin Li
1051*ec63e07aSXin Li ARG_32(1), // arg2
1052*ec63e07aSXin Li JEQ32(PR_SET_VMA_ANON_NAME, ALLOW),
1053*ec63e07aSXin Li
1054*ec63e07aSXin Li LABEL(&labels, prctl_end),
1055*ec63e07aSXin Li };
1056*ec63e07aSXin Li });
1057*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mremap,
1058*ec63e07aSXin Li {
1059*ec63e07aSXin Li ARG_32(3),
1060*ec63e07aSXin Li JEQ32(MREMAP_MAYMOVE | MREMAP_FIXED, ALLOW),
1061*ec63e07aSXin Li });
1062*ec63e07aSXin Li AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
1063*ec63e07aSXin Li return {
1064*ec63e07aSXin Li ARG_32(2), // prot
1065*ec63e07aSXin Li JEQ32(PROT_NONE, JUMP(&labels, prot_none)),
1066*ec63e07aSXin Li JEQ32(PROT_READ, JUMP(&labels, prot_read)),
1067*ec63e07aSXin Li JEQ32(PROT_READ | PROT_WRITE, JUMP(&labels, prot_RW_or_RX)),
1068*ec63e07aSXin Li JEQ32(PROT_READ | PROT_EXEC, JUMP(&labels, prot_RW_or_RX)),
1069*ec63e07aSXin Li
1070*ec63e07aSXin Li // PROT_NONE
1071*ec63e07aSXin Li LABEL(&labels, prot_none),
1072*ec63e07aSXin Li ARG_32(3), // flags
1073*ec63e07aSXin Li JEQ32(MAP_PRIVATE | MAP_ANONYMOUS, ALLOW),
1074*ec63e07aSXin Li JEQ32(MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, ALLOW),
1075*ec63e07aSXin Li JUMP(&labels, mmap_end),
1076*ec63e07aSXin Li
1077*ec63e07aSXin Li // PROT_READ
1078*ec63e07aSXin Li LABEL(&labels, prot_read),
1079*ec63e07aSXin Li ARG_32(3), // flags
1080*ec63e07aSXin Li JEQ32(MAP_SHARED, ALLOW),
1081*ec63e07aSXin Li JEQ32(MAP_PRIVATE, ALLOW),
1082*ec63e07aSXin Li JEQ32(MAP_PRIVATE | MAP_FIXED, ALLOW),
1083*ec63e07aSXin Li JUMP(&labels, mmap_end),
1084*ec63e07aSXin Li
1085*ec63e07aSXin Li // PROT_READ | PROT_WRITE
1086*ec63e07aSXin Li // PROT_READ | PROT_EXEC
1087*ec63e07aSXin Li LABEL(&labels, prot_RW_or_RX),
1088*ec63e07aSXin Li ARG_32(3), // flags
1089*ec63e07aSXin Li JEQ32(MAP_PRIVATE | MAP_FIXED, ALLOW),
1090*ec63e07aSXin Li
1091*ec63e07aSXin Li LABEL(&labels, mmap_end),
1092*ec63e07aSXin Li };
1093*ec63e07aSXin Li });
1094*ec63e07aSXin Li #endif
1095*ec63e07aSXin Li
1096*ec63e07aSXin Li AllowAccess();
1097*ec63e07aSXin Li AllowOpen();
1098*ec63e07aSXin Li AllowRead();
1099*ec63e07aSXin Li AllowStat();
1100*ec63e07aSXin Li AllowSyscalls({__NR_lseek,
1101*ec63e07aSXin Li #ifdef __NR__llseek
1102*ec63e07aSXin Li __NR__llseek, // Newer glibc on PPC
1103*ec63e07aSXin Li #endif
1104*ec63e07aSXin Li __NR_close, __NR_munmap});
1105*ec63e07aSXin Li AddPolicyOnSyscall(__NR_mprotect, {
1106*ec63e07aSXin Li ARG_32(2),
1107*ec63e07aSXin Li JEQ32(PROT_READ, ALLOW),
1108*ec63e07aSXin Li JEQ32(PROT_NONE, ALLOW),
1109*ec63e07aSXin Li JEQ32(PROT_READ | PROT_WRITE, ALLOW),
1110*ec63e07aSXin Li JEQ32(PROT_READ | PROT_EXEC, ALLOW),
1111*ec63e07aSXin Li });
1112*ec63e07aSXin Li AllowStaticStartup();
1113*ec63e07aSXin Li
1114*ec63e07aSXin Li return AddPolicyOnMmap([](bpf_labels& labels) -> std::vector<sock_filter> {
1115*ec63e07aSXin Li return {
1116*ec63e07aSXin Li ARG_32(2), // prot
1117*ec63e07aSXin Li JEQ32(PROT_READ | PROT_EXEC, JUMP(&labels, prot_exec)),
1118*ec63e07aSXin Li JEQ32(PROT_READ | PROT_WRITE, JUMP(&labels, prot_read_write)),
1119*ec63e07aSXin Li JNE32(PROT_READ, JUMP(&labels, mmap_end)),
1120*ec63e07aSXin Li
1121*ec63e07aSXin Li // PROT_READ
1122*ec63e07aSXin Li ARG_32(3), // flags
1123*ec63e07aSXin Li JEQ32(MAP_PRIVATE, ALLOW),
1124*ec63e07aSXin Li JUMP(&labels, mmap_end),
1125*ec63e07aSXin Li
1126*ec63e07aSXin Li // PROT_READ | PROT_WRITE
1127*ec63e07aSXin Li LABEL(&labels, prot_read_write),
1128*ec63e07aSXin Li ARG_32(3), // flags
1129*ec63e07aSXin Li JEQ32(MAP_FILE | MAP_PRIVATE | MAP_FIXED | MAP_DENYWRITE, ALLOW),
1130*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, ALLOW),
1131*ec63e07aSXin Li JEQ32(MAP_ANONYMOUS | MAP_PRIVATE, ALLOW),
1132*ec63e07aSXin Li JUMP(&labels, mmap_end),
1133*ec63e07aSXin Li
1134*ec63e07aSXin Li // PROT_READ | PROT_EXEC
1135*ec63e07aSXin Li LABEL(&labels, prot_exec),
1136*ec63e07aSXin Li ARG_32(3), // flags
1137*ec63e07aSXin Li JEQ32(MAP_FILE | MAP_PRIVATE | MAP_DENYWRITE, ALLOW),
1138*ec63e07aSXin Li
1139*ec63e07aSXin Li LABEL(&labels, mmap_end),
1140*ec63e07aSXin Li };
1141*ec63e07aSXin Li });
1142*ec63e07aSXin Li }
1143*ec63e07aSXin Li
AddPolicyOnSyscall(uint32_t num,absl::Span<const sock_filter> policy)1144*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(
1145*ec63e07aSXin Li uint32_t num, absl::Span<const sock_filter> policy) {
1146*ec63e07aSXin Li return AddPolicyOnSyscalls({num}, policy);
1147*ec63e07aSXin Li }
1148*ec63e07aSXin Li
AddPolicyOnSyscall(uint32_t num,BpfFunc f)1149*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnSyscall(uint32_t num, BpfFunc f) {
1150*ec63e07aSXin Li return AddPolicyOnSyscalls({num}, f);
1151*ec63e07aSXin Li }
1152*ec63e07aSXin Li
AddPolicyOnSyscalls(absl::Span<const uint32_t> nums,absl::Span<const sock_filter> policy)1153*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnSyscalls(
1154*ec63e07aSXin Li absl::Span<const uint32_t> nums, absl::Span<const sock_filter> policy) {
1155*ec63e07aSXin Li if (nums.empty()) {
1156*ec63e07aSXin Li SetError(absl::InvalidArgumentError(
1157*ec63e07aSXin Li "Cannot add a policy for empty list of syscalls"));
1158*ec63e07aSXin Li return *this;
1159*ec63e07aSXin Li }
1160*ec63e07aSXin Li std::deque<sock_filter> out;
1161*ec63e07aSXin Li // Insert and verify the policy.
1162*ec63e07aSXin Li out.insert(out.end(), policy.begin(), policy.end());
1163*ec63e07aSXin Li for (size_t i = 0; i < out.size(); ++i) {
1164*ec63e07aSXin Li sock_filter& filter = out[i];
1165*ec63e07aSXin Li const size_t max_jump = out.size() - i - 1;
1166*ec63e07aSXin Li if (!CheckBpfBounds(filter, max_jump)) {
1167*ec63e07aSXin Li SetError(absl::InvalidArgumentError("bpf jump out of bounds"));
1168*ec63e07aSXin Li return *this;
1169*ec63e07aSXin Li }
1170*ec63e07aSXin Li // Syscall arch is expected as TRACE value
1171*ec63e07aSXin Li if (filter.code == (BPF_RET | BPF_K) &&
1172*ec63e07aSXin Li (filter.k & SECCOMP_RET_ACTION) == SECCOMP_RET_TRACE &&
1173*ec63e07aSXin Li (filter.k & SECCOMP_RET_DATA) != Syscall::GetHostArch()) {
1174*ec63e07aSXin Li LOG(WARNING) << "SANDBOX2_TRACE should be used in policy instead of "
1175*ec63e07aSXin Li "TRACE(value)";
1176*ec63e07aSXin Li filter = SANDBOX2_TRACE;
1177*ec63e07aSXin Li }
1178*ec63e07aSXin Li }
1179*ec63e07aSXin Li // Pre-/Postcondition: Syscall number loaded into A register
1180*ec63e07aSXin Li out.push_back(LOAD_SYSCALL_NR);
1181*ec63e07aSXin Li if (out.size() > std::numeric_limits<uint32_t>::max()) {
1182*ec63e07aSXin Li SetError(absl::InvalidArgumentError("syscall policy is too long"));
1183*ec63e07aSXin Li return *this;
1184*ec63e07aSXin Li }
1185*ec63e07aSXin Li // Create jumps for each syscall.
1186*ec63e07aSXin Li size_t do_policy_loc = out.size();
1187*ec63e07aSXin Li // Iterate in reverse order and prepend instruction, so that jumps can be
1188*ec63e07aSXin Li // calculated easily.
1189*ec63e07aSXin Li constexpr size_t kMaxShortJump = 255;
1190*ec63e07aSXin Li bool last = true;
1191*ec63e07aSXin Li for (auto it = std::rbegin(nums); it != std::rend(nums); ++it) {
1192*ec63e07aSXin Li if (*it == __NR_bpf || *it == __NR_ptrace) {
1193*ec63e07aSXin Li SetError(absl::InvalidArgumentError(
1194*ec63e07aSXin Li "cannot add policy for bpf/ptrace syscall"));
1195*ec63e07aSXin Li return *this;
1196*ec63e07aSXin Li }
1197*ec63e07aSXin Li // If syscall is not matched try with the next one.
1198*ec63e07aSXin Li uint8_t jf = 0;
1199*ec63e07aSXin Li // If last syscall on the list does not match skip the policy by jumping
1200*ec63e07aSXin Li // over it.
1201*ec63e07aSXin Li if (last) {
1202*ec63e07aSXin Li if (out.size() > kMaxShortJump) {
1203*ec63e07aSXin Li out.push_front(
1204*ec63e07aSXin Li BPF_STMT(BPF_JMP + BPF_JA, static_cast<uint32_t>(out.size())));
1205*ec63e07aSXin Li } else {
1206*ec63e07aSXin Li jf = out.size();
1207*ec63e07aSXin Li }
1208*ec63e07aSXin Li last = false;
1209*ec63e07aSXin Li }
1210*ec63e07aSXin Li // Add a helper absolute jump if needed - the policy/last helper jump is
1211*ec63e07aSXin Li // out of reach of a short jump.
1212*ec63e07aSXin Li if ((out.size() - do_policy_loc) > kMaxShortJump) {
1213*ec63e07aSXin Li out.push_front(BPF_STMT(
1214*ec63e07aSXin Li BPF_JMP + BPF_JA, static_cast<uint32_t>(out.size() - policy.size())));
1215*ec63e07aSXin Li do_policy_loc = out.size();
1216*ec63e07aSXin Li ++jf;
1217*ec63e07aSXin Li }
1218*ec63e07aSXin Li uint8_t jt = out.size() - do_policy_loc;
1219*ec63e07aSXin Li out.push_front(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, *it, jt, jf));
1220*ec63e07aSXin Li }
1221*ec63e07aSXin Li user_policy_.insert(user_policy_.end(), out.begin(), out.end());
1222*ec63e07aSXin Li return *this;
1223*ec63e07aSXin Li }
1224*ec63e07aSXin Li
AddPolicyOnSyscalls(absl::Span<const uint32_t> nums,BpfFunc f)1225*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnSyscalls(
1226*ec63e07aSXin Li absl::Span<const uint32_t> nums, BpfFunc f) {
1227*ec63e07aSXin Li return AddPolicyOnSyscalls(nums, ResolveBpfFunc(f));
1228*ec63e07aSXin Li }
1229*ec63e07aSXin Li
AddPolicyOnMmap(absl::Span<const sock_filter> policy)1230*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnMmap(
1231*ec63e07aSXin Li absl::Span<const sock_filter> policy) {
1232*ec63e07aSXin Li return AddPolicyOnSyscalls(kMmapSyscalls, policy);
1233*ec63e07aSXin Li }
1234*ec63e07aSXin Li
AddPolicyOnMmap(BpfFunc f)1235*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddPolicyOnMmap(BpfFunc f) {
1236*ec63e07aSXin Li return AddPolicyOnSyscalls(kMmapSyscalls, f);
1237*ec63e07aSXin Li }
1238*ec63e07aSXin Li
DangerDefaultAllowAll()1239*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::DangerDefaultAllowAll() {
1240*ec63e07aSXin Li return DefaultAction(AllowAllSyscalls());
1241*ec63e07aSXin Li }
1242*ec63e07aSXin Li
DefaultAction(AllowAllSyscalls)1243*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::DefaultAction(AllowAllSyscalls) {
1244*ec63e07aSXin Li default_action_ = ALLOW;
1245*ec63e07aSXin Li return *this;
1246*ec63e07aSXin Li }
1247*ec63e07aSXin Li
DefaultAction(TraceAllSyscalls)1248*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::DefaultAction(TraceAllSyscalls) {
1249*ec63e07aSXin Li default_action_ = SANDBOX2_TRACE;
1250*ec63e07aSXin Li return *this;
1251*ec63e07aSXin Li }
1252*ec63e07aSXin Li
ValidateAbsolutePath(absl::string_view path)1253*ec63e07aSXin Li absl::StatusOr<std::string> PolicyBuilder::ValidateAbsolutePath(
1254*ec63e07aSXin Li absl::string_view path) {
1255*ec63e07aSXin Li if (!file::IsAbsolutePath(path)) {
1256*ec63e07aSXin Li return absl::InvalidArgumentError(
1257*ec63e07aSXin Li absl::StrCat("Path is not absolute: '", path, "'"));
1258*ec63e07aSXin Li }
1259*ec63e07aSXin Li return ValidatePath(path);
1260*ec63e07aSXin Li }
1261*ec63e07aSXin Li
ValidatePath(absl::string_view path)1262*ec63e07aSXin Li absl::StatusOr<std::string> PolicyBuilder::ValidatePath(
1263*ec63e07aSXin Li absl::string_view path) {
1264*ec63e07aSXin Li std::string fixed_path = file::CleanPath(path);
1265*ec63e07aSXin Li if (fixed_path != path) {
1266*ec63e07aSXin Li return absl::InvalidArgumentError(absl::StrCat(
1267*ec63e07aSXin Li "Path was not normalized. '", path, "' != '", fixed_path, "'"));
1268*ec63e07aSXin Li }
1269*ec63e07aSXin Li return fixed_path;
1270*ec63e07aSXin Li }
1271*ec63e07aSXin Li
ResolveBpfFunc(BpfFunc f)1272*ec63e07aSXin Li std::vector<sock_filter> PolicyBuilder::ResolveBpfFunc(BpfFunc f) {
1273*ec63e07aSXin Li bpf_labels l = {0};
1274*ec63e07aSXin Li
1275*ec63e07aSXin Li std::vector<sock_filter> policy = f(l);
1276*ec63e07aSXin Li if (bpf_resolve_jumps(&l, policy.data(), policy.size()) != 0) {
1277*ec63e07aSXin Li SetError(absl::InternalError("Cannot resolve bpf jumps"));
1278*ec63e07aSXin Li }
1279*ec63e07aSXin Li
1280*ec63e07aSXin Li return policy;
1281*ec63e07aSXin Li }
1282*ec63e07aSXin Li
TryBuild()1283*ec63e07aSXin Li absl::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
1284*ec63e07aSXin Li if (!last_status_.ok()) {
1285*ec63e07aSXin Li return last_status_;
1286*ec63e07aSXin Li }
1287*ec63e07aSXin Li
1288*ec63e07aSXin Li if (user_policy_.size() > kMaxUserPolicyLength) {
1289*ec63e07aSXin Li return absl::FailedPreconditionError(
1290*ec63e07aSXin Li absl::StrCat("User syscall policy is to long (", user_policy_.size(),
1291*ec63e07aSXin Li " > ", kMaxUserPolicyLength, ")."));
1292*ec63e07aSXin Li }
1293*ec63e07aSXin Li
1294*ec63e07aSXin Li // Using `new` to access a non-public constructor.
1295*ec63e07aSXin Li auto output = absl::WrapUnique(new Policy());
1296*ec63e07aSXin Li
1297*ec63e07aSXin Li if (already_built_) {
1298*ec63e07aSXin Li return absl::FailedPreconditionError("Can only build policy once.");
1299*ec63e07aSXin Li }
1300*ec63e07aSXin Li
1301*ec63e07aSXin Li if (use_namespaces_) {
1302*ec63e07aSXin Li if (allow_unrestricted_networking_ && hostname_ != kDefaultHostname) {
1303*ec63e07aSXin Li return absl::FailedPreconditionError(
1304*ec63e07aSXin Li "Cannot set hostname without network namespaces.");
1305*ec63e07aSXin Li }
1306*ec63e07aSXin Li output->namespace_ =
1307*ec63e07aSXin Li Namespace(allow_unrestricted_networking_, std::move(mounts_), hostname_,
1308*ec63e07aSXin Li allow_mount_propagation_);
1309*ec63e07aSXin Li }
1310*ec63e07aSXin Li
1311*ec63e07aSXin Li output->collect_stacktrace_on_signal_ = collect_stacktrace_on_signal_;
1312*ec63e07aSXin Li output->collect_stacktrace_on_violation_ = collect_stacktrace_on_violation_;
1313*ec63e07aSXin Li output->collect_stacktrace_on_timeout_ = collect_stacktrace_on_timeout_;
1314*ec63e07aSXin Li output->collect_stacktrace_on_kill_ = collect_stacktrace_on_kill_;
1315*ec63e07aSXin Li output->collect_stacktrace_on_exit_ = collect_stacktrace_on_exit_;
1316*ec63e07aSXin Li output->user_policy_ = std::move(user_policy_);
1317*ec63e07aSXin Li if (default_action_) {
1318*ec63e07aSXin Li output->user_policy_.push_back(*default_action_);
1319*ec63e07aSXin Li }
1320*ec63e07aSXin Li output->user_policy_.insert(output->user_policy_.end(),
1321*ec63e07aSXin Li overridable_policy_.begin(),
1322*ec63e07aSXin Li overridable_policy_.end());
1323*ec63e07aSXin Li output->user_policy_handles_bpf_ = user_policy_handles_bpf_;
1324*ec63e07aSXin Li output->user_policy_handles_ptrace_ = user_policy_handles_ptrace_;
1325*ec63e07aSXin Li
1326*ec63e07aSXin Li PolicyBuilderDescription pb_description;
1327*ec63e07aSXin Li
1328*ec63e07aSXin Li StoreDescription(&pb_description);
1329*ec63e07aSXin Li output->policy_builder_description_ = pb_description;
1330*ec63e07aSXin Li output->allowed_hosts_ = std::move(allowed_hosts_);
1331*ec63e07aSXin Li already_built_ = true;
1332*ec63e07aSXin Li return std::move(output);
1333*ec63e07aSXin Li }
1334*ec63e07aSXin Li
AddFile(absl::string_view path,bool is_ro)1335*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddFile(absl::string_view path, bool is_ro) {
1336*ec63e07aSXin Li return AddFileAt(path, path, is_ro);
1337*ec63e07aSXin Li }
1338*ec63e07aSXin Li
AddFileAt(absl::string_view outside,absl::string_view inside,bool is_ro)1339*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddFileAt(absl::string_view outside,
1340*ec63e07aSXin Li absl::string_view inside, bool is_ro) {
1341*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1342*ec63e07aSXin Li return AddFileAtIfNamespaced(outside, inside, is_ro);
1343*ec63e07aSXin Li }
1344*ec63e07aSXin Li
AddFileIfNamespaced(absl::string_view path,bool is_ro)1345*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddFileIfNamespaced(absl::string_view path,
1346*ec63e07aSXin Li bool is_ro) {
1347*ec63e07aSXin Li return AddFileAtIfNamespaced(path, path, is_ro);
1348*ec63e07aSXin Li }
1349*ec63e07aSXin Li
AddFileAtIfNamespaced(absl::string_view outside,absl::string_view inside,bool is_ro)1350*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddFileAtIfNamespaced(absl::string_view outside,
1351*ec63e07aSXin Li absl::string_view inside,
1352*ec63e07aSXin Li bool is_ro) {
1353*ec63e07aSXin Li auto valid_outside = ValidateAbsolutePath(outside);
1354*ec63e07aSXin Li if (!valid_outside.ok()) {
1355*ec63e07aSXin Li SetError(valid_outside.status());
1356*ec63e07aSXin Li return *this;
1357*ec63e07aSXin Li }
1358*ec63e07aSXin Li
1359*ec63e07aSXin Li if (absl::StartsWith(*valid_outside, "/proc/self") &&
1360*ec63e07aSXin Li *valid_outside != "/proc/self/cpuset") {
1361*ec63e07aSXin Li SetError(absl::InvalidArgumentError(
1362*ec63e07aSXin Li absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
1363*ec63e07aSXin Li "whole /proc instead. You tried to mount ",
1364*ec63e07aSXin Li outside)));
1365*ec63e07aSXin Li return *this;
1366*ec63e07aSXin Li }
1367*ec63e07aSXin Li
1368*ec63e07aSXin Li if (!is_ro && IsOnReadOnlyDev(*valid_outside)) {
1369*ec63e07aSXin Li SetError(absl::FailedPreconditionError(
1370*ec63e07aSXin Li absl::StrCat("Cannot add ", outside,
1371*ec63e07aSXin Li " as read-write as it's on a read-only device")));
1372*ec63e07aSXin Li return *this;
1373*ec63e07aSXin Li }
1374*ec63e07aSXin Li
1375*ec63e07aSXin Li if (auto status = mounts_.AddFileAt(*valid_outside, inside, is_ro);
1376*ec63e07aSXin Li !status.ok()) {
1377*ec63e07aSXin Li SetError(
1378*ec63e07aSXin Li absl::InternalError(absl::StrCat("Could not add file ", outside, " => ",
1379*ec63e07aSXin Li inside, ": ", status.message())));
1380*ec63e07aSXin Li }
1381*ec63e07aSXin Li return *this;
1382*ec63e07aSXin Li }
1383*ec63e07aSXin Li
AddLibrariesForBinary(absl::string_view path,absl::string_view ld_library_path)1384*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
1385*ec63e07aSXin Li absl::string_view path, absl::string_view ld_library_path) {
1386*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1387*ec63e07aSXin Li
1388*ec63e07aSXin Li auto valid_path = ValidatePath(path);
1389*ec63e07aSXin Li if (!valid_path.ok()) {
1390*ec63e07aSXin Li SetError(valid_path.status());
1391*ec63e07aSXin Li return *this;
1392*ec63e07aSXin Li }
1393*ec63e07aSXin Li
1394*ec63e07aSXin Li if (auto status = mounts_.AddMappingsForBinary(*valid_path, ld_library_path);
1395*ec63e07aSXin Li !status.ok()) {
1396*ec63e07aSXin Li SetError(absl::InternalError(absl::StrCat(
1397*ec63e07aSXin Li "Could not add libraries for ", *valid_path, ": ", status.message())));
1398*ec63e07aSXin Li }
1399*ec63e07aSXin Li return *this;
1400*ec63e07aSXin Li }
1401*ec63e07aSXin Li
AddLibrariesForBinary(int fd,absl::string_view ld_library_path)1402*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddLibrariesForBinary(
1403*ec63e07aSXin Li int fd, absl::string_view ld_library_path) {
1404*ec63e07aSXin Li return AddLibrariesForBinary(absl::StrCat("/proc/self/fd/", fd),
1405*ec63e07aSXin Li ld_library_path);
1406*ec63e07aSXin Li }
1407*ec63e07aSXin Li
AddDirectory(absl::string_view path,bool is_ro)1408*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddDirectory(absl::string_view path, bool is_ro) {
1409*ec63e07aSXin Li return AddDirectoryAt(path, path, is_ro);
1410*ec63e07aSXin Li }
1411*ec63e07aSXin Li
AddDirectoryAt(absl::string_view outside,absl::string_view inside,bool is_ro)1412*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddDirectoryAt(absl::string_view outside,
1413*ec63e07aSXin Li absl::string_view inside,
1414*ec63e07aSXin Li bool is_ro) {
1415*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1416*ec63e07aSXin Li return AddDirectoryAtIfNamespaced(outside, inside, is_ro);
1417*ec63e07aSXin Li }
1418*ec63e07aSXin Li
AddDirectoryIfNamespaced(absl::string_view path,bool is_ro)1419*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddDirectoryIfNamespaced(absl::string_view path,
1420*ec63e07aSXin Li bool is_ro) {
1421*ec63e07aSXin Li return AddDirectoryAtIfNamespaced(path, path, is_ro);
1422*ec63e07aSXin Li }
1423*ec63e07aSXin Li
AddDirectoryAtIfNamespaced(absl::string_view outside,absl::string_view inside,bool is_ro)1424*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddDirectoryAtIfNamespaced(
1425*ec63e07aSXin Li absl::string_view outside, absl::string_view inside, bool is_ro) {
1426*ec63e07aSXin Li auto valid_outside = ValidateAbsolutePath(outside);
1427*ec63e07aSXin Li if (!valid_outside.ok()) {
1428*ec63e07aSXin Li SetError(valid_outside.status());
1429*ec63e07aSXin Li return *this;
1430*ec63e07aSXin Li }
1431*ec63e07aSXin Li
1432*ec63e07aSXin Li if (absl::StartsWith(*valid_outside, "/proc/self")) {
1433*ec63e07aSXin Li SetError(absl::InvalidArgumentError(
1434*ec63e07aSXin Li absl::StrCat("Cannot add /proc/self mounts, you need to mount the "
1435*ec63e07aSXin Li "whole /proc instead. You tried to mount ",
1436*ec63e07aSXin Li outside)));
1437*ec63e07aSXin Li return *this;
1438*ec63e07aSXin Li }
1439*ec63e07aSXin Li
1440*ec63e07aSXin Li if (!is_ro && IsOnReadOnlyDev(*valid_outside)) {
1441*ec63e07aSXin Li SetError(absl::FailedPreconditionError(
1442*ec63e07aSXin Li absl::StrCat("Cannot add ", outside,
1443*ec63e07aSXin Li " as read-write as it's on a read-only device")));
1444*ec63e07aSXin Li return *this;
1445*ec63e07aSXin Li }
1446*ec63e07aSXin Li
1447*ec63e07aSXin Li if (absl::Status status =
1448*ec63e07aSXin Li mounts_.AddDirectoryAt(*valid_outside, inside, is_ro);
1449*ec63e07aSXin Li !status.ok()) {
1450*ec63e07aSXin Li SetError(absl::InternalError(absl::StrCat("Could not add directory ",
1451*ec63e07aSXin Li outside, " => ", inside, ": ",
1452*ec63e07aSXin Li status.message())));
1453*ec63e07aSXin Li return *this;
1454*ec63e07aSXin Li }
1455*ec63e07aSXin Li return *this;
1456*ec63e07aSXin Li }
1457*ec63e07aSXin Li
AddTmpfs(absl::string_view inside,size_t size)1458*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddTmpfs(absl::string_view inside, size_t size) {
1459*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1460*ec63e07aSXin Li
1461*ec63e07aSXin Li if (auto status = mounts_.AddTmpfs(inside, size); !status.ok()) {
1462*ec63e07aSXin Li SetError(absl::InternalError(absl::StrCat("Could not mount tmpfs ", inside,
1463*ec63e07aSXin Li ": ", status.message())));
1464*ec63e07aSXin Li }
1465*ec63e07aSXin Li return *this;
1466*ec63e07aSXin Li }
1467*ec63e07aSXin Li
1468*ec63e07aSXin Li // Use Allow(UnrestrictedNetworking()) instead.
AllowUnrestrictedNetworking()1469*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowUnrestrictedNetworking() {
1470*ec63e07aSXin Li return Allow(UnrestrictedNetworking());
1471*ec63e07aSXin Li }
1472*ec63e07aSXin Li
SetHostname(absl::string_view hostname)1473*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::SetHostname(absl::string_view hostname) {
1474*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1475*ec63e07aSXin Li hostname_ = std::string(hostname);
1476*ec63e07aSXin Li
1477*ec63e07aSXin Li return *this;
1478*ec63e07aSXin Li }
1479*ec63e07aSXin Li
CollectStacktracesOnViolation(bool enable)1480*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::CollectStacktracesOnViolation(bool enable) {
1481*ec63e07aSXin Li collect_stacktrace_on_violation_ = enable;
1482*ec63e07aSXin Li return *this;
1483*ec63e07aSXin Li }
1484*ec63e07aSXin Li
CollectStacktracesOnSignal(bool enable)1485*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::CollectStacktracesOnSignal(bool enable) {
1486*ec63e07aSXin Li collect_stacktrace_on_signal_ = enable;
1487*ec63e07aSXin Li return *this;
1488*ec63e07aSXin Li }
1489*ec63e07aSXin Li
CollectStacktracesOnTimeout(bool enable)1490*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::CollectStacktracesOnTimeout(bool enable) {
1491*ec63e07aSXin Li collect_stacktrace_on_timeout_ = enable;
1492*ec63e07aSXin Li return *this;
1493*ec63e07aSXin Li }
1494*ec63e07aSXin Li
CollectStacktracesOnKill(bool enable)1495*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::CollectStacktracesOnKill(bool enable) {
1496*ec63e07aSXin Li collect_stacktrace_on_kill_ = enable;
1497*ec63e07aSXin Li return *this;
1498*ec63e07aSXin Li }
1499*ec63e07aSXin Li
CollectStacktracesOnExit(bool enable)1500*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::CollectStacktracesOnExit(bool enable) {
1501*ec63e07aSXin Li collect_stacktrace_on_exit_ = enable;
1502*ec63e07aSXin Li return *this;
1503*ec63e07aSXin Li }
1504*ec63e07aSXin Li
AddNetworkProxyPolicy()1505*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddNetworkProxyPolicy() {
1506*ec63e07aSXin Li if (allowed_hosts_) {
1507*ec63e07aSXin Li SetError(absl::FailedPreconditionError(
1508*ec63e07aSXin Li "AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy can be called "
1509*ec63e07aSXin Li "at most once"));
1510*ec63e07aSXin Li return *this;
1511*ec63e07aSXin Li }
1512*ec63e07aSXin Li
1513*ec63e07aSXin Li allowed_hosts_ = AllowedHosts();
1514*ec63e07aSXin Li
1515*ec63e07aSXin Li AllowFutexOp(FUTEX_WAKE);
1516*ec63e07aSXin Li AllowFutexOp(FUTEX_WAIT);
1517*ec63e07aSXin Li AllowFutexOp(FUTEX_WAIT_BITSET);
1518*ec63e07aSXin Li AllowDup();
1519*ec63e07aSXin Li AllowSyscalls({
1520*ec63e07aSXin Li __NR_recvmsg,
1521*ec63e07aSXin Li __NR_close,
1522*ec63e07aSXin Li __NR_gettid,
1523*ec63e07aSXin Li });
1524*ec63e07aSXin Li AddPolicyOnSyscall(__NR_socket, {
1525*ec63e07aSXin Li ARG_32(0),
1526*ec63e07aSXin Li JEQ32(AF_INET, ALLOW),
1527*ec63e07aSXin Li JEQ32(AF_INET6, ALLOW),
1528*ec63e07aSXin Li });
1529*ec63e07aSXin Li AddPolicyOnSyscall(__NR_getsockopt,
1530*ec63e07aSXin Li [](bpf_labels& labels) -> std::vector<sock_filter> {
1531*ec63e07aSXin Li return {
1532*ec63e07aSXin Li ARG_32(1),
1533*ec63e07aSXin Li JNE32(SOL_SOCKET, JUMP(&labels, getsockopt_end)),
1534*ec63e07aSXin Li ARG_32(2),
1535*ec63e07aSXin Li JEQ32(SO_TYPE, ALLOW),
1536*ec63e07aSXin Li LABEL(&labels, getsockopt_end),
1537*ec63e07aSXin Li };
1538*ec63e07aSXin Li });
1539*ec63e07aSXin Li #ifdef SAPI_PPC64_LE
1540*ec63e07aSXin Li AddPolicyOnSyscall(__NR_socketcall, {
1541*ec63e07aSXin Li ARG_32(0),
1542*ec63e07aSXin Li JEQ32(SYS_SOCKET, ALLOW),
1543*ec63e07aSXin Li JEQ32(SYS_GETSOCKOPT, ALLOW),
1544*ec63e07aSXin Li JEQ32(SYS_RECVMSG, ALLOW),
1545*ec63e07aSXin Li });
1546*ec63e07aSXin Li #endif
1547*ec63e07aSXin Li return *this;
1548*ec63e07aSXin Li }
1549*ec63e07aSXin Li
AddNetworkProxyHandlerPolicy()1550*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AddNetworkProxyHandlerPolicy() {
1551*ec63e07aSXin Li AddNetworkProxyPolicy();
1552*ec63e07aSXin Li AllowSyscall(__NR_rt_sigreturn);
1553*ec63e07aSXin Li
1554*ec63e07aSXin Li AddPolicyOnSyscall(__NR_rt_sigaction, {
1555*ec63e07aSXin Li ARG_32(0),
1556*ec63e07aSXin Li JEQ32(SIGSYS, ALLOW),
1557*ec63e07aSXin Li });
1558*ec63e07aSXin Li
1559*ec63e07aSXin Li AddPolicyOnSyscall(__NR_rt_sigprocmask, {
1560*ec63e07aSXin Li ARG_32(0),
1561*ec63e07aSXin Li JEQ32(SIG_UNBLOCK, ALLOW),
1562*ec63e07aSXin Li });
1563*ec63e07aSXin Li
1564*ec63e07aSXin Li AddPolicyOnSyscall(__NR_connect, {TRAP(0)});
1565*ec63e07aSXin Li #ifdef SAPI_PPC64_LE
1566*ec63e07aSXin Li AddPolicyOnSyscall(__NR_socketcall, {
1567*ec63e07aSXin Li ARG_32(0),
1568*ec63e07aSXin Li JEQ32(SYS_CONNECT, TRAP(0)),
1569*ec63e07aSXin Li });
1570*ec63e07aSXin Li #endif
1571*ec63e07aSXin Li return *this;
1572*ec63e07aSXin Li }
1573*ec63e07aSXin Li
TrapPtrace()1574*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::TrapPtrace() {
1575*ec63e07aSXin Li if (handled_syscalls_.insert(__NR_ptrace).second) {
1576*ec63e07aSXin Li user_policy_.insert(user_policy_.end(), {SYSCALL(__NR_ptrace, TRAP(0))});
1577*ec63e07aSXin Li user_policy_handles_ptrace_ = true;
1578*ec63e07aSXin Li }
1579*ec63e07aSXin Li return *this;
1580*ec63e07aSXin Li }
1581*ec63e07aSXin Li
SetRootWritable()1582*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::SetRootWritable() {
1583*ec63e07aSXin Li EnableNamespaces(); // NOLINT(clang-diagnostic-deprecated-declarations)
1584*ec63e07aSXin Li mounts_.SetRootWritable();
1585*ec63e07aSXin Li
1586*ec63e07aSXin Li return *this;
1587*ec63e07aSXin Li }
1588*ec63e07aSXin Li
StoreDescription(PolicyBuilderDescription * pb_description)1589*ec63e07aSXin Li void PolicyBuilder::StoreDescription(PolicyBuilderDescription* pb_description) {
1590*ec63e07aSXin Li for (const auto& handled_syscall : handled_syscalls_) {
1591*ec63e07aSXin Li pb_description->add_handled_syscalls(handled_syscall);
1592*ec63e07aSXin Li }
1593*ec63e07aSXin Li }
1594*ec63e07aSXin Li
AllowIPv4(const std::string & ip_and_mask,uint32_t port)1595*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowIPv4(const std::string& ip_and_mask,
1596*ec63e07aSXin Li uint32_t port) {
1597*ec63e07aSXin Li if (!allowed_hosts_) {
1598*ec63e07aSXin Li SetError(absl::FailedPreconditionError(
1599*ec63e07aSXin Li "AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
1600*ec63e07aSXin Li "before adding IP rules"));
1601*ec63e07aSXin Li return *this;
1602*ec63e07aSXin Li }
1603*ec63e07aSXin Li
1604*ec63e07aSXin Li absl::Status status = allowed_hosts_->AllowIPv4(ip_and_mask, port);
1605*ec63e07aSXin Li if (!status.ok()) {
1606*ec63e07aSXin Li SetError(status);
1607*ec63e07aSXin Li }
1608*ec63e07aSXin Li return *this;
1609*ec63e07aSXin Li }
1610*ec63e07aSXin Li
AllowIPv6(const std::string & ip_and_mask,uint32_t port)1611*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::AllowIPv6(const std::string& ip_and_mask,
1612*ec63e07aSXin Li uint32_t port) {
1613*ec63e07aSXin Li if (!allowed_hosts_) {
1614*ec63e07aSXin Li SetError(absl::FailedPreconditionError(
1615*ec63e07aSXin Li "AddNetworkProxyPolicy or AddNetworkProxyHandlerPolicy must be called "
1616*ec63e07aSXin Li "before adding IP rules"));
1617*ec63e07aSXin Li return *this;
1618*ec63e07aSXin Li }
1619*ec63e07aSXin Li
1620*ec63e07aSXin Li absl::Status status = allowed_hosts_->AllowIPv6(ip_and_mask, port);
1621*ec63e07aSXin Li if (!status.ok()) {
1622*ec63e07aSXin Li SetError(status);
1623*ec63e07aSXin Li }
1624*ec63e07aSXin Li return *this;
1625*ec63e07aSXin Li }
1626*ec63e07aSXin Li
SetError(const absl::Status & status)1627*ec63e07aSXin Li PolicyBuilder& PolicyBuilder::SetError(const absl::Status& status) {
1628*ec63e07aSXin Li LOG(ERROR) << status;
1629*ec63e07aSXin Li last_status_ = status;
1630*ec63e07aSXin Li return *this;
1631*ec63e07aSXin Li }
1632*ec63e07aSXin Li
1633*ec63e07aSXin Li } // namespace sandbox2
1634