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