OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/sandbox_linux/nacl_sandbox_linux.h" | 5 #include "components/nacl/loader/sandbox_linux/nacl_sandbox_linux.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <unistd.h> | 11 #include <unistd.h> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/callback.h" | 14 #include "base/callback.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
| 17 #include "base/files/scoped_file.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
19 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
21 #include "components/nacl/common/nacl_switches.h" | 22 #include "components/nacl/common/nacl_switches.h" |
22 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" | 23 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" |
23 #include "components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.h" | 24 #include "components/nacl/loader/sandbox_linux/nacl_bpf_sandbox_linux.h" |
| 25 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" |
24 #include "sandbox/linux/services/credentials.h" | 26 #include "sandbox/linux/services/credentials.h" |
25 #include "sandbox/linux/services/thread_helpers.h" | 27 #include "sandbox/linux/services/thread_helpers.h" |
26 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" | 28 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
27 | 29 |
28 namespace nacl { | 30 namespace nacl { |
29 | 31 |
30 namespace { | 32 namespace { |
31 | 33 |
32 // This is a poor man's check on whether we are sandboxed. | 34 // This is a poor man's check on whether we are sandboxed. |
33 bool IsSandboxed() { | 35 bool IsSandboxed() { |
34 int proc_fd = open("/proc/self/exe", O_RDONLY); | 36 int proc_fd = open("/proc/self/exe", O_RDONLY); |
35 if (proc_fd >= 0) { | 37 if (proc_fd >= 0) { |
36 PCHECK(0 == IGNORE_EINTR(close(proc_fd))); | 38 PCHECK(0 == IGNORE_EINTR(close(proc_fd))); |
37 return false; | 39 return false; |
38 } | 40 } |
39 return true; | 41 return true; |
40 } | 42 } |
41 | 43 |
| 44 // Open a new file descriptor to /proc/self/task/ by using |
| 45 // |proc_fd|. |
| 46 base::ScopedFD GetProcSelfTask(int proc_fd) { |
| 47 base::ScopedFD proc_self_task(HANDLE_EINTR( |
| 48 openat(proc_fd, "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); |
| 49 PCHECK(proc_self_task.is_valid()); |
| 50 return proc_self_task.Pass(); |
| 51 } |
| 52 |
42 } // namespace | 53 } // namespace |
43 | 54 |
44 NaClSandbox::NaClSandbox() | 55 NaClSandbox::NaClSandbox() |
45 : layer_one_enabled_(false), | 56 : layer_one_enabled_(false), |
46 layer_one_sealed_(false), | 57 layer_one_sealed_(false), |
47 layer_two_enabled_(false), | 58 layer_two_enabled_(false), |
48 layer_two_is_nonsfi_(false), | 59 layer_two_is_nonsfi_(false), |
49 proc_fd_(-1), | 60 proc_fd_(-1), |
50 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { | 61 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { |
51 proc_fd_.reset( | 62 proc_fd_.reset( |
52 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC))); | 63 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC))); |
53 PCHECK(proc_fd_.is_valid()); | 64 PCHECK(proc_fd_.is_valid()); |
| 65 // Determine if the kernel supports seccomp-bpf and let it cache the |
| 66 // result. This must be done before any sandbox is engaged. |
| 67 sandbox::SandboxBPF::SupportsSeccompSandbox(); |
54 } | 68 } |
55 | 69 |
56 NaClSandbox::~NaClSandbox() { | 70 NaClSandbox::~NaClSandbox() { |
57 } | 71 } |
58 | 72 |
59 bool NaClSandbox::IsSingleThreaded() { | 73 bool NaClSandbox::IsSingleThreaded() { |
60 CHECK(proc_fd_.is_valid()); | 74 CHECK(proc_fd_.is_valid()); |
61 base::ScopedFD proc_self_task(HANDLE_EINTR(openat( | 75 base::ScopedFD proc_self_task(GetProcSelfTask(proc_fd_.get())); |
62 proc_fd_.get(), "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); | |
63 PCHECK(proc_self_task.is_valid()); | |
64 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get()); | 76 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get()); |
65 } | 77 } |
66 | 78 |
67 bool NaClSandbox::HasOpenDirectory() { | 79 bool NaClSandbox::HasOpenDirectory() { |
68 CHECK(proc_fd_.is_valid()); | 80 CHECK(proc_fd_.is_valid()); |
69 sandbox::Credentials credentials; | 81 sandbox::Credentials credentials; |
70 return credentials.HasOpenDirectory(proc_fd_.get()); | 82 return credentials.HasOpenDirectory(proc_fd_.get()); |
71 } | 83 } |
72 | 84 |
73 void NaClSandbox::InitializeLayerOneSandbox() { | 85 void NaClSandbox::InitializeLayerOneSandbox() { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 } | 119 } |
108 } | 120 } |
109 | 121 |
110 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) { | 122 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) { |
111 // seccomp-bpf only applies to the current thread, so it's critical to only | 123 // seccomp-bpf only applies to the current thread, so it's critical to only |
112 // have a single thread running here. | 124 // have a single thread running here. |
113 DCHECK(!layer_one_sealed_); | 125 DCHECK(!layer_one_sealed_); |
114 CHECK(IsSingleThreaded()); | 126 CHECK(IsSingleThreaded()); |
115 CheckForExpectedNumberOfOpenFds(); | 127 CheckForExpectedNumberOfOpenFds(); |
116 | 128 |
| 129 base::ScopedFD proc_self_task(GetProcSelfTask(proc_fd_.get())); |
| 130 |
117 if (uses_nonsfi_mode) { | 131 if (uses_nonsfi_mode) { |
118 layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox(); | 132 layer_two_enabled_ = |
| 133 nacl::nonsfi::InitializeBPFSandbox(proc_self_task.Pass()); |
119 layer_two_is_nonsfi_ = true; | 134 layer_two_is_nonsfi_ = true; |
120 } else { | 135 } else { |
121 layer_two_enabled_ = nacl::InitializeBPFSandbox(); | 136 layer_two_enabled_ = nacl::InitializeBPFSandbox(proc_self_task.Pass()); |
122 } | 137 } |
123 } | 138 } |
124 | 139 |
125 void NaClSandbox::SealLayerOneSandbox() { | 140 void NaClSandbox::SealLayerOneSandbox() { |
126 if (!layer_two_enabled_) { | 141 if (!layer_two_enabled_) { |
127 // If nothing prevents us, check that there is no superfluous directory | 142 // If nothing prevents us, check that there is no superfluous directory |
128 // open. | 143 // open. |
129 CHECK(!HasOpenDirectory()); | 144 CHECK(!HasOpenDirectory()); |
130 } | 145 } |
131 proc_fd_.reset(); | 146 proc_fd_.reset(); |
(...skipping 24 matching lines...) Expand all Loading... |
156 static const char kNoBpfMsg[] = | 171 static const char kNoBpfMsg[] = |
157 "The seccomp-bpf sandbox is not engaged for NaCl:"; | 172 "The seccomp-bpf sandbox is not engaged for NaCl:"; |
158 if (can_be_no_sandbox) | 173 if (can_be_no_sandbox) |
159 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg; | 174 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg; |
160 else | 175 else |
161 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg; | 176 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg; |
162 } | 177 } |
163 } | 178 } |
164 | 179 |
165 } // namespace nacl | 180 } // namespace nacl |
OLD | NEW |