Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/loader/nacl_sandbox_linux.h" | 5 #include "components/nacl/loader/nacl_sandbox_linux.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <linux/net.h> | |
| 8 #include <signal.h> | 9 #include <signal.h> |
| 9 #include <sys/ptrace.h> | 10 #include <sys/ptrace.h> |
| 11 #include <sys/syscall.h> | |
| 10 | 12 |
| 11 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 12 #include "base/callback.h" | 14 #include "base/callback.h" |
| 13 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 16 | 18 |
| 17 #if defined(USE_SECCOMP_BPF) | 19 #if defined(USE_SECCOMP_BPF) |
| 18 #include "content/public/common/sandbox_init.h" | 20 #include "content/public/common/sandbox_init.h" |
| 21 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | |
| 22 #include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h" | |
| 19 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | 23 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
| 20 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" | 24 #include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h" |
| 25 #include "sandbox/linux/seccomp-bpf/trap.h" | |
| 21 #include "sandbox/linux/services/linux_syscalls.h" | 26 #include "sandbox/linux/services/linux_syscalls.h" |
| 22 | 27 |
| 23 using sandbox::ErrorCode; | 28 using sandbox::ErrorCode; |
| 24 using sandbox::SandboxBPF; | 29 using sandbox::SandboxBPF; |
| 25 using sandbox::SandboxBPFPolicy; | 30 using sandbox::SandboxBPFPolicy; |
| 26 | 31 |
| 27 namespace { | 32 namespace { |
| 28 | 33 |
| 29 // On ARM and x86_64, System V shared memory calls have each their own system | 34 // On ARM and x86_64, System V shared memory calls have each their own system |
| 30 // call, while on i386 they are multiplexed. | 35 // call, while on i386 they are multiplexed. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 case __NR_sched_setscheduler: | 120 case __NR_sched_setscheduler: |
| 116 case __NR_setpriority: | 121 case __NR_setpriority: |
| 117 case __NR_sysinfo: | 122 case __NR_sysinfo: |
| 118 // __NR_times needed as clock() is called by CommandBufferHelper, which is | 123 // __NR_times needed as clock() is called by CommandBufferHelper, which is |
| 119 // used by NaCl applications that use Pepper's 3D interfaces. | 124 // used by NaCl applications that use Pepper's 3D interfaces. |
| 120 // See crbug.com/264856 for details. | 125 // See crbug.com/264856 for details. |
| 121 case __NR_times: | 126 case __NR_times: |
| 122 case __NR_uname: | 127 case __NR_uname: |
| 123 return ErrorCode(ErrorCode::ERR_ALLOWED); | 128 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 124 case __NR_ptrace: | 129 case __NR_ptrace: |
| 130 // For RunSandboxSanityChecks(). | |
| 125 return ErrorCode(EPERM); | 131 return ErrorCode(EPERM); |
| 126 default: | 132 default: |
| 127 // TODO(jln): look into getting rid of System V shared memory: | 133 // TODO(jln): look into getting rid of System V shared memory: |
| 128 // platform_qualify/linux/sysv_shm_and_mmap.c makes it a requirement, but | 134 // platform_qualify/linux/sysv_shm_and_mmap.c makes it a requirement, but |
| 129 // it may not be needed in all cases. Chromium renderers don't need | 135 // it may not be needed in all cases. Chromium renderers don't need |
| 130 // System V shared memory on Aura. | 136 // System V shared memory on Aura. |
| 131 #if defined(__x86_64__) || defined(__arm__) | 137 #if defined(__x86_64__) || defined(__arm__) |
| 132 if (IsSystemVSharedMemory(sysno)) | 138 if (IsSystemVSharedMemory(sysno)) |
| 133 return ErrorCode(ErrorCode::ERR_ALLOWED); | 139 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 134 #elif defined(__i386__) | 140 #elif defined(__i386__) |
| 135 if (IsSystemVIpc(sysno)) | 141 if (IsSystemVIpc(sysno)) |
| 136 return ErrorCode(ErrorCode::ERR_ALLOWED); | 142 return ErrorCode(ErrorCode::ERR_ALLOWED); |
| 137 #endif | 143 #endif |
| 138 return baseline_policy_->EvaluateSyscall(sb, sysno); | 144 return baseline_policy_->EvaluateSyscall(sb, sysno); |
| 139 } | 145 } |
| 140 NOTREACHED(); | 146 NOTREACHED(); |
| 141 // GCC wants this. | 147 // GCC wants this. |
| 142 return ErrorCode(EPERM); | 148 return ErrorCode(EPERM); |
| 143 } | 149 } |
| 144 | 150 |
| 151 // The seccomp sandbox policy for NaCl non-SFI mode. Note that this | |
| 152 // policy must be as strong as possible, as non-SFI mode heavily | |
| 153 // depends on seccomp sandbox. | |
| 154 class NonSfiNaClBPFSandboxPolicy : public SandboxBPFPolicy { | |
| 155 public: | |
| 156 explicit NonSfiNaClBPFSandboxPolicy() | |
| 157 : baseline_policy_(content::GetBPFSandboxBaselinePolicy()) { | |
| 158 } | |
| 159 virtual ~NonSfiNaClBPFSandboxPolicy() {} | |
| 160 | |
| 161 virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler, | |
| 162 int system_call_number) const OVERRIDE; | |
| 163 | |
| 164 private: | |
| 165 scoped_ptr<SandboxBPFPolicy> baseline_policy_; | |
| 166 DISALLOW_COPY_AND_ASSIGN(NonSfiNaClBPFSandboxPolicy); | |
| 167 }; | |
| 168 | |
| 169 ErrorCode NonSfiNaClBPFSandboxPolicy::EvaluateSyscall( | |
| 170 sandbox::SandboxBPF* sb, int sysno) const { | |
| 171 DCHECK(baseline_policy_); | |
| 172 ErrorCode ret = baseline_policy_->EvaluateSyscall(sb, sysno); | |
|
Mark Seaborn
2014/03/18 23:53:58
You're falling through to the baseline policy. I
jln (very slow on Chromium)
2014/03/20 00:54:53
I absolutely agree with Mark here. We need a short
hamaji
2014/03/24 15:56:37
Done. I also stopped using sandbox::Restrict* as t
| |
| 173 switch (sysno) { | |
| 174 // __NR_times needed as clock() is called by CommandBufferHelper, which is | |
| 175 // used by NaCl applications that use Pepper's 3D interfaces. | |
| 176 // See crbug.com/264856 for details. | |
| 177 case __NR_times: | |
| 178 ret = ErrorCode(ErrorCode::ERR_ALLOWED); | |
| 179 break; | |
| 180 | |
| 181 // Conditionally allowed syscalls: | |
| 182 case __NR_clone: { | |
| 183 // We allow clone only for new thread creation. | |
| 184 ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
| 185 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | | |
| 186 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | | |
| 187 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID, | |
| 188 ErrorCode(ErrorCode::ERR_ALLOWED), | |
| 189 sb->Trap(sandbox::SIGSYSCloneFailure, NULL)); | |
| 190 break; | |
| 191 } | |
| 192 case __NR_prctl: | |
| 193 // We only allow PR_SET_NAME, PR_SET_DUMPABLE, and PR_GET_DUMPABLE. | |
|
Mark Seaborn
2014/03/18 23:53:58
I don't think these are operations that should be
hamaji
2014/03/24 15:56:37
I stopped using RestrictPrctl. Now it returns EPER
| |
| 194 ret = sandbox::RestrictPrctl(sb); | |
| 195 break; | |
| 196 #if defined(__i686__) | |
|
Mark Seaborn
2014/03/18 23:53:58
__i386__ would be preferred.
hamaji
2014/03/24 15:56:37
Done.
| |
| 197 case __NR_socketcall: { | |
| 198 // We only allow socketpair, sendmsg, and recvmsg. | |
| 199 ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
| 200 SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED), | |
| 201 sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
| 202 SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED), | |
| 203 sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, | |
| 204 SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED), | |
| 205 ErrorCode(EPERM)))); | |
| 206 break; | |
| 207 } | |
| 208 #endif | |
| 209 | |
| 210 // It is allowed to call the following syscalls, but they just | |
| 211 // return EPERM. | |
| 212 case __NR_ptrace: | |
| 213 // For RunSandboxSanityChecks(). | |
| 214 ret = ErrorCode(EPERM); | |
| 215 break; | |
| 216 case __NR_set_robust_list: | |
| 217 // glibc uses this for its pthread implementation. If we return | |
| 218 // EPERM for this, glibc will stop using this. | |
| 219 // TODO(hamaji): newlib does not use this. Make this SIGTRAP once | |
| 220 // we have switched to newlib. | |
| 221 ret = ErrorCode(EPERM); | |
| 222 break; | |
| 223 #if !defined(__x86_64__) | |
| 224 case __NR_getegid32: | |
| 225 case __NR_geteuid32: | |
| 226 case __NR_getgid32: | |
| 227 case __NR_getuid32: | |
| 228 #endif | |
| 229 // third_party/libevent uses them, but we can just return -1 from | |
| 230 // them as it is just checking getuid() != geteuid() and | |
| 231 // getgid() != getegid() | |
| 232 ret = ErrorCode(EPERM); | |
| 233 break; | |
| 234 #if !defined(__arm__) | |
|
Mark Seaborn
2014/03/18 23:53:58
Should be "defined(__i386__) || defined(__x86_64__
hamaji
2014/03/24 15:56:37
Done.
| |
| 235 case __NR_time: | |
| 236 // This is obsolete in ARM EABI, but x86 glibc indirectly calls | |
| 237 // this in sysconf. | |
| 238 case __NR_modify_ldt: | |
| 239 // nacl_helper calls this from service_runtime/linux/x86/nacl_ldt.c | |
|
Mark Seaborn
2014/03/18 23:53:58
But this doesn't apply to Non-SFI Mode.
hamaji
2014/03/24 15:56:37
It seems current nacl_helper always calls NaClTlsI
| |
| 240 ret = ErrorCode(EPERM); | |
| 241 break; | |
| 242 #endif | |
| 243 | |
| 244 // Followings are restricted syscalls. | |
| 245 | |
| 246 // glibc internally calls brk in its memory allocation. | |
|
Mark Seaborn
2014/03/18 23:53:58
glibc does call brk(), but it doesn't require it t
jln (very slow on Chromium)
2014/03/20 00:54:53
Yes, in other words, just EPERM it.
hamaji
2014/03/24 15:56:37
Oops, my comment was wrong. brk was called by tcma
Mark Seaborn
2014/03/28 16:41:39
Does tcmalloc currently require brk(), or does it
| |
| 247 // TODO(hamaji): Uncomment this once newlib switch has been done. | |
| 248 // case __NR_brk: | |
| 249 case __NR_capget: | |
|
Mark Seaborn
2014/03/18 23:53:58
This is a blacklist of disallowed syscalls, but I
hamaji
2014/03/24 15:56:37
Done.
| |
| 250 case __NR_dup3: | |
| 251 case __NR_epoll_create1: | |
| 252 case __NR_fcntl: | |
| 253 case __NR_fork: | |
| 254 case __NR_get_robust_list: | |
| 255 case __NR_getgroups: | |
| 256 case __NR_getpid: | |
| 257 case __NR_getppid: | |
| 258 case __NR_getresgid: | |
| 259 case __NR_getresuid: | |
| 260 case __NR_getsid: | |
| 261 case __NR_kill: | |
| 262 case __NR_mlock: | |
| 263 case __NR_munlock: | |
| 264 case __NR_pause: | |
| 265 case __NR_pipe2: | |
| 266 case __NR_poll: | |
| 267 case __NR_ppoll: | |
| 268 case __NR_pselect6: | |
| 269 case __NR_readv: | |
| 270 case __NR_recvmmsg: | |
| 271 case __NR_rt_sigaction: | |
| 272 case __NR_sendmmsg: | |
| 273 case __NR_tgkill: | |
| 274 case __NR_tkill: | |
| 275 case __NR_wait4: | |
| 276 case __NR_waitid: | |
| 277 case __NR_writev: | |
| 278 // We do not need 32bit versions of them. | |
| 279 case __NR_fstat: | |
| 280 case __NR_lseek: | |
| 281 #if !defined(__arm__) | |
| 282 // They do not exist on ARM EABI. | |
| 283 case __NR_select: | |
| 284 #endif | |
| 285 #if defined(__i686__) | |
| 286 // This is i686 only. | |
| 287 case __NR_waitpid: | |
| 288 #endif | |
| 289 #if !defined(__i686__) | |
| 290 // i686 uses socketcall instead of them. | |
| 291 case __NR_sendto: | |
| 292 case __NR_shutdown: | |
| 293 case __NR_recvfrom: | |
| 294 #if defined(__arm__) | |
| 295 case __NR_send: | |
| 296 case __NR_recv: | |
| 297 #endif | |
| 298 #endif | |
| 299 #if !defined(__x86_64__) | |
| 300 // They do not exist on x86-64. | |
| 301 case __NR__newselect: | |
| 302 case __NR_getegid: | |
| 303 case __NR_geteuid: | |
| 304 case __NR_getgid: | |
| 305 case __NR_getgroups32: | |
| 306 case __NR_getresgid32: | |
| 307 case __NR_getresuid32: | |
| 308 case __NR_getuid: | |
| 309 case __NR_rt_sigprocmask: | |
| 310 case __NR_rt_sigreturn: | |
| 311 case __NR_sigprocmask: | |
| 312 case __NR_sigreturn: | |
| 313 #endif | |
| 314 ret = sb->Trap(sandbox::CrashSIGSYS_Handler, NULL); | |
| 315 break; | |
| 316 } | |
| 317 return ret; | |
| 318 } | |
| 319 | |
| 145 void RunSandboxSanityChecks() { | 320 void RunSandboxSanityChecks() { |
| 146 errno = 0; | 321 errno = 0; |
| 147 // Make a ptrace request with an invalid PID. | 322 // Make a ptrace request with an invalid PID. |
| 148 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); | 323 long ptrace_ret = ptrace(PTRACE_PEEKUSER, -1 /* pid */, NULL, NULL); |
| 149 CHECK_EQ(-1, ptrace_ret); | 324 CHECK_EQ(-1, ptrace_ret); |
| 150 // Without the sandbox on, this ptrace call would ESRCH instead. | 325 // Without the sandbox on, this ptrace call would ESRCH instead. |
| 151 CHECK_EQ(EPERM, errno); | 326 CHECK_EQ(EPERM, errno); |
| 152 } | 327 } |
| 153 | 328 |
| 154 } // namespace | 329 } // namespace |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 165 #if defined(USE_SECCOMP_BPF) | 340 #if defined(USE_SECCOMP_BPF) |
| 166 bool sandbox_is_initialized = content::InitializeSandbox( | 341 bool sandbox_is_initialized = content::InitializeSandbox( |
| 167 scoped_ptr<SandboxBPFPolicy>(new NaClBPFSandboxPolicy())); | 342 scoped_ptr<SandboxBPFPolicy>(new NaClBPFSandboxPolicy())); |
| 168 if (sandbox_is_initialized) { | 343 if (sandbox_is_initialized) { |
| 169 RunSandboxSanityChecks(); | 344 RunSandboxSanityChecks(); |
| 170 return true; | 345 return true; |
| 171 } | 346 } |
| 172 #endif // defined(USE_SECCOMP_BPF) | 347 #endif // defined(USE_SECCOMP_BPF) |
| 173 return false; | 348 return false; |
| 174 } | 349 } |
| 350 | |
| 351 bool InitializeBPFSandboxForNonSfi() { | |
| 352 #if defined(USE_SECCOMP_BPF) | |
| 353 bool sandbox_is_initialized = content::InitializeSandbox( | |
|
hamaji
2014/03/14 12:46:23
I thought we should add something like
#if !defi
jln (very slow on Chromium)
2014/03/20 00:54:53
We should not return false in non SFI mode. We sho
hamaji
2014/03/24 15:56:37
Done.
| |
| 354 scoped_ptr<SandboxBPFPolicy>(new NonSfiNaClBPFSandboxPolicy())); | |
| 355 if (sandbox_is_initialized) { | |
| 356 RunSandboxSanityChecks(); | |
| 357 return true; | |
| 358 } | |
| 359 #endif // defined(USE_SECCOMP_BPF) | |
| 360 return false; | |
| 361 } | |
| OLD | NEW |