baseline_policy.cc revision 010d83a9304c5a91596085d917d248abff47903a
1// Copyright (c) 2013 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-helpers/baseline_policy.h"
6
7#include <errno.h>
8#include <sys/mman.h>
9#include <sys/socket.h>
10#include <sys/syscall.h>
11#include <sys/types.h>
12#include <unistd.h>
13
14#include "base/logging.h"
15#include "build/build_config.h"
16#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
17#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
18#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
19#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
20#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
21#include "sandbox/linux/services/linux_syscalls.h"
22
23// Changing this implementation will have an effect on *all* policies.
24// Currently this means: Renderer/Worker, GPU, Flash and NaCl.
25
26namespace sandbox {
27
28namespace {
29
30bool IsBaselinePolicyAllowed(int sysno) {
31  return SyscallSets::IsAllowedAddressSpaceAccess(sysno) ||
32         SyscallSets::IsAllowedBasicScheduler(sysno) ||
33         SyscallSets::IsAllowedEpoll(sysno) ||
34         SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) ||
35         SyscallSets::IsAllowedGeneralIo(sysno) ||
36         SyscallSets::IsAllowedGetOrModifySocket(sysno) ||
37         SyscallSets::IsAllowedGettime(sysno) ||
38         SyscallSets::IsAllowedPrctl(sysno) ||
39         SyscallSets::IsAllowedProcessStartOrDeath(sysno) ||
40         SyscallSets::IsAllowedSignalHandling(sysno) ||
41         SyscallSets::IsFutex(sysno) ||
42         SyscallSets::IsGetSimpleId(sysno) ||
43         SyscallSets::IsKernelInternalApi(sysno) ||
44#if defined(__arm__)
45         SyscallSets::IsArmPrivate(sysno) ||
46#endif
47         SyscallSets::IsAllowedOperationOnFd(sysno);
48}
49
50// System calls that will trigger the crashing SIGSYS handler.
51bool IsBaselinePolicyWatched(int sysno) {
52  return SyscallSets::IsAdminOperation(sysno) ||
53         SyscallSets::IsAdvancedScheduler(sysno) ||
54         SyscallSets::IsAdvancedTimer(sysno) ||
55         SyscallSets::IsAsyncIo(sysno) ||
56         SyscallSets::IsDebug(sysno) ||
57         SyscallSets::IsEventFd(sysno) ||
58         SyscallSets::IsExtendedAttributes(sysno) ||
59         SyscallSets::IsFaNotify(sysno) ||
60         SyscallSets::IsFsControl(sysno) ||
61         SyscallSets::IsGlobalFSViewChange(sysno) ||
62         SyscallSets::IsGlobalProcessEnvironment(sysno) ||
63         SyscallSets::IsGlobalSystemStatus(sysno) ||
64         SyscallSets::IsInotify(sysno) ||
65         SyscallSets::IsKernelModule(sysno) ||
66         SyscallSets::IsKeyManagement(sysno) ||
67         SyscallSets::IsKill(sysno) ||
68         SyscallSets::IsMessageQueue(sysno) ||
69         SyscallSets::IsMisc(sysno) ||
70#if defined(__x86_64__)
71         SyscallSets::IsNetworkSocketInformation(sysno) ||
72#endif
73         SyscallSets::IsNuma(sysno) ||
74         SyscallSets::IsProcessGroupOrSession(sysno) ||
75#if defined(__i386__)
76         SyscallSets::IsSocketCall(sysno) ||
77#endif
78#if defined(__arm__)
79         SyscallSets::IsArmPciConfig(sysno) ||
80#endif
81         SyscallSets::IsTimer(sysno);
82}
83
84// |fs_denied_errno| is the errno return for denied filesystem access.
85ErrorCode EvaluateSyscallImpl(int fs_denied_errno,
86                              pid_t current_pid,
87                              SandboxBPF* sandbox,
88                              int sysno) {
89#if defined(ADDRESS_SANITIZER)
90  if (sysno == __NR_sigaltstack) {
91    // Required for better stack overflow detection in ASan. Disallowed in
92    // non-ASan builds.
93    return ErrorCode(ErrorCode::ERR_ALLOWED);
94  }
95#endif
96  if (IsBaselinePolicyAllowed(sysno)) {
97    return ErrorCode(ErrorCode::ERR_ALLOWED);
98  }
99
100  if (sysno == __NR_clone) {
101    return RestrictCloneToThreadsAndEPERMFork(sandbox);
102  }
103
104#if defined(__x86_64__) || defined(__arm__)
105  if (sysno == __NR_socketpair) {
106    // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
107    COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
108    return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX,
109                         ErrorCode(ErrorCode::ERR_ALLOWED),
110                         sandbox->Trap(CrashSIGSYS_Handler, NULL));
111  }
112#endif
113
114  if (sysno == __NR_madvise) {
115    // Only allow MADV_DONTNEED (aka MADV_FREE).
116    return sandbox->Cond(2, ErrorCode::TP_32BIT,
117                         ErrorCode::OP_EQUAL, MADV_DONTNEED,
118                         ErrorCode(ErrorCode::ERR_ALLOWED),
119                         ErrorCode(EPERM));
120  }
121
122#if defined(__i386__) || defined(__x86_64__)
123  if (sysno == __NR_mmap)
124    return RestrictMmapFlags(sandbox);
125#endif
126
127#if defined(__i386__) || defined(__arm__)
128  if (sysno == __NR_mmap2)
129    return RestrictMmapFlags(sandbox);
130#endif
131
132  if (sysno == __NR_mprotect)
133    return RestrictMprotectFlags(sandbox);
134
135  if (sysno == __NR_fcntl)
136    return RestrictFcntlCommands(sandbox);
137
138#if defined(__i386__) || defined(__arm__)
139  if (sysno == __NR_fcntl64)
140    return RestrictFcntlCommands(sandbox);
141#endif
142
143  if (SyscallSets::IsKill(sysno)) {
144    return RestrictKillTarget(current_pid, sandbox, sysno);
145  }
146
147  if (SyscallSets::IsFileSystem(sysno) ||
148      SyscallSets::IsCurrentDirectory(sysno)) {
149    return ErrorCode(fs_denied_errno);
150  }
151
152  if (SyscallSets::IsAnySystemV(sysno)) {
153    return ErrorCode(EPERM);
154  }
155
156  if (SyscallSets::IsUmask(sysno) ||
157      SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) ||
158      SyscallSets::IsDeniedGetOrModifySocket(sysno) ||
159      SyscallSets::IsProcessPrivilegeChange(sysno)) {
160    return ErrorCode(EPERM);
161  }
162
163#if defined(__i386__)
164  if (SyscallSets::IsSocketCall(sysno))
165    return RestrictSocketcallCommand(sandbox);
166#endif
167
168  if (IsBaselinePolicyWatched(sysno)) {
169    // Previously unseen syscalls. TODO(jln): some of these should
170    // be denied gracefully right away.
171    return sandbox->Trap(CrashSIGSYS_Handler, NULL);
172  }
173
174  // In any other case crash the program with our SIGSYS handler.
175  return sandbox->Trap(CrashSIGSYS_Handler, NULL);
176}
177
178}  // namespace.
179
180// Unfortunately C++03 doesn't allow delegated constructors.
181// Call other constructor when C++11 lands.
182BaselinePolicy::BaselinePolicy()
183    : fs_denied_errno_(EPERM), current_pid_(syscall(__NR_getpid)) {}
184
185BaselinePolicy::BaselinePolicy(int fs_denied_errno)
186    : fs_denied_errno_(fs_denied_errno), current_pid_(syscall(__NR_getpid)) {}
187
188BaselinePolicy::~BaselinePolicy() {
189  // Make sure that this policy is created, used and destroyed by a single
190  // process.
191  DCHECK_EQ(syscall(__NR_getpid), current_pid_);
192}
193
194ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox,
195                                          int sysno) const {
196  // Make sure that this policy is used in the creating process.
197  if (1 == sysno) {
198    DCHECK_EQ(syscall(__NR_getpid), current_pid_);
199  }
200  return EvaluateSyscallImpl(fs_denied_errno_, current_pid_, sandbox, sysno);
201}
202
203}  // namespace sandbox.
204