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
24 namespace sandbox {
25
26 namespace {
27
IsBaselinePolicyAllowed(int sysno)28 bool 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.
IsBaselinePolicyWatched(int sysno)50 bool 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.
EvaluateSyscallImpl(int fs_denied_errno,SandboxBPF * sandbox,int sysno)84 ErrorCode 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.
BaselinePolicy()162 BaselinePolicy::BaselinePolicy()
163 : fs_denied_errno_(EPERM) {}
164
BaselinePolicy(int fs_denied_errno)165 BaselinePolicy::BaselinePolicy(int fs_denied_errno)
166 : fs_denied_errno_(fs_denied_errno) {}
167
~BaselinePolicy()168 BaselinePolicy::~BaselinePolicy() {}
169
EvaluateSyscall(SandboxBPF * sandbox,int sysno) const170 ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox,
171 int sysno) const {
172 return EvaluateSyscallImpl(fs_denied_errno_, sandbox, sysno);
173 }
174
175 } // namespace sandbox.
176