OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <dirent.h> | 5 #include <dirent.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <sys/resource.h> | 7 #include <sys/resource.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 #include <sys/time.h> | 9 #include <sys/time.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/posix/eintr_wrapper.h" | 21 #include "base/posix/eintr_wrapper.h" |
22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
23 #include "base/time/time.h" | 23 #include "base/time/time.h" |
24 #include "build/build_config.h" | 24 #include "build/build_config.h" |
25 #include "content/common/sandbox_linux/sandbox_linux.h" | 25 #include "content/common/sandbox_linux/sandbox_linux.h" |
26 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" | 26 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h" |
27 #include "content/public/common/content_switches.h" | 27 #include "content/public/common/content_switches.h" |
28 #include "content/public/common/sandbox_linux.h" | 28 #include "content/public/common/sandbox_linux.h" |
29 #include "sandbox/linux/services/credentials.h" | 29 #include "sandbox/linux/services/credentials.h" |
30 #include "sandbox/linux/services/thread_helpers.h" | 30 #include "sandbox/linux/services/thread_helpers.h" |
| 31 #include "sandbox/linux/services/yama.h" |
31 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" | 32 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" |
32 | 33 |
| 34 using sandbox::Yama; |
| 35 |
33 namespace { | 36 namespace { |
34 | 37 |
35 struct FDCloser { | 38 struct FDCloser { |
36 inline void operator()(int* fd) const { | 39 inline void operator()(int* fd) const { |
37 DCHECK(fd); | 40 DCHECK(fd); |
38 PCHECK(0 == IGNORE_EINTR(close(*fd))); | 41 PCHECK(0 == IGNORE_EINTR(close(*fd))); |
39 *fd = -1; | 42 *fd = -1; |
40 } | 43 } |
41 }; | 44 }; |
42 | 45 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } // namespace | 100 } // namespace |
98 | 101 |
99 namespace content { | 102 namespace content { |
100 | 103 |
101 LinuxSandbox::LinuxSandbox() | 104 LinuxSandbox::LinuxSandbox() |
102 : proc_fd_(-1), | 105 : proc_fd_(-1), |
103 seccomp_bpf_started_(false), | 106 seccomp_bpf_started_(false), |
104 sandbox_status_flags_(kSandboxLinuxInvalid), | 107 sandbox_status_flags_(kSandboxLinuxInvalid), |
105 pre_initialized_(false), | 108 pre_initialized_(false), |
106 seccomp_bpf_supported_(false), | 109 seccomp_bpf_supported_(false), |
| 110 yama_is_enforcing_(false), |
107 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { | 111 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) { |
108 if (setuid_sandbox_client_ == NULL) { | 112 if (setuid_sandbox_client_ == NULL) { |
109 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; | 113 LOG(FATAL) << "Failed to instantiate the setuid sandbox client."; |
110 } | 114 } |
111 } | 115 } |
112 | 116 |
113 LinuxSandbox::~LinuxSandbox() { | 117 LinuxSandbox::~LinuxSandbox() { |
114 } | 118 } |
115 | 119 |
116 LinuxSandbox* LinuxSandbox::GetInstance() { | 120 LinuxSandbox* LinuxSandbox::GetInstance() { |
117 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); | 121 LinuxSandbox* instance = Singleton<LinuxSandbox>::get(); |
118 CHECK(instance); | 122 CHECK(instance); |
119 return instance; | 123 return instance; |
120 } | 124 } |
121 | 125 |
122 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) | 126 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) |
123 // ASan API call to notify the tool the sandbox is going to be turned on. | 127 // ASan API call to notify the tool the sandbox is going to be turned on. |
124 extern "C" void __sanitizer_sandbox_on_notify(void *reserved); | 128 extern "C" void __sanitizer_sandbox_on_notify(void *reserved); |
125 #endif | 129 #endif |
126 | 130 |
127 void LinuxSandbox::PreinitializeSandbox() { | 131 void LinuxSandbox::PreinitializeSandbox() { |
128 CHECK(!pre_initialized_); | 132 CHECK(!pre_initialized_); |
129 seccomp_bpf_supported_ = false; | 133 seccomp_bpf_supported_ = false; |
130 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) | 134 #if defined(ADDRESS_SANITIZER) && defined(OS_LINUX) |
131 // ASan needs to open some resources before the sandbox is enabled. | 135 // ASan needs to open some resources before the sandbox is enabled. |
132 // This should not fork, not launch threads, not open a directory. | 136 // This should not fork, not launch threads, not open a directory. |
133 __sanitizer_sandbox_on_notify(/*reserved*/NULL); | 137 __sanitizer_sandbox_on_notify(/*reserved*/ NULL); |
134 #endif | 138 #endif |
135 | 139 |
136 #if !defined(NDEBUG) | 140 #if !defined(NDEBUG) |
137 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't | 141 // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't |
138 // produce a sandbox escape in Release mode. | 142 // produce a sandbox escape in Release mode. |
139 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); | 143 proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY); |
140 CHECK_GE(proc_fd_, 0); | 144 CHECK_GE(proc_fd_, 0); |
141 #endif // !defined(NDEBUG) | 145 #endif // !defined(NDEBUG) |
142 // We "pre-warm" the code that detects supports for seccomp BPF. | 146 // We "pre-warm" the code that detects supports for seccomp BPF. |
143 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { | 147 if (SandboxSeccompBPF::IsSeccompBPFDesired()) { |
144 if (!SandboxSeccompBPF::SupportsSandbox()) { | 148 if (!SandboxSeccompBPF::SupportsSandbox()) { |
145 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; | 149 VLOG(1) << "Lacking support for seccomp-bpf sandbox."; |
146 } else { | 150 } else { |
147 seccomp_bpf_supported_ = true; | 151 seccomp_bpf_supported_ = true; |
148 } | 152 } |
149 } | 153 } |
| 154 |
| 155 // Yama is a "global", system-level status. We assume it will not regress |
| 156 // after startup. |
| 157 const int yama_status = Yama::GetStatus(); |
| 158 yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) && |
| 159 (yama_status & Yama::STATUS_ENFORCING); |
150 pre_initialized_ = true; | 160 pre_initialized_ = true; |
151 } | 161 } |
152 | 162 |
153 bool LinuxSandbox::InitializeSandbox() { | 163 bool LinuxSandbox::InitializeSandbox() { |
154 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 164 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
155 return linux_sandbox->InitializeSandboxImpl(); | 165 return linux_sandbox->InitializeSandboxImpl(); |
156 } | 166 } |
157 | 167 |
158 void LinuxSandbox::StopThread(base::Thread* thread) { | 168 void LinuxSandbox::StopThread(base::Thread* thread) { |
159 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); | 169 LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance(); |
(...skipping 12 matching lines...) Expand all Loading... |
172 if (setuid_sandbox_client_->IsInNewNETNamespace()) | 182 if (setuid_sandbox_client_->IsInNewNETNamespace()) |
173 sandbox_status_flags_ |= kSandboxLinuxNetNS; | 183 sandbox_status_flags_ |= kSandboxLinuxNetNS; |
174 } | 184 } |
175 | 185 |
176 // We report whether the sandbox will be activated when renderers, workers | 186 // We report whether the sandbox will be activated when renderers, workers |
177 // and PPAPI plugins go through sandbox initialization. | 187 // and PPAPI plugins go through sandbox initialization. |
178 if (seccomp_bpf_supported() && | 188 if (seccomp_bpf_supported() && |
179 SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) { | 189 SandboxSeccompBPF::ShouldEnableSeccompBPF(switches::kRendererProcess)) { |
180 sandbox_status_flags_ |= kSandboxLinuxSeccompBPF; | 190 sandbox_status_flags_ |= kSandboxLinuxSeccompBPF; |
181 } | 191 } |
| 192 |
| 193 if (yama_is_enforcing_) { |
| 194 sandbox_status_flags_ |= kSandboxLinuxYama; |
| 195 } |
182 } | 196 } |
183 | 197 |
184 return sandbox_status_flags_; | 198 return sandbox_status_flags_; |
185 } | 199 } |
186 | 200 |
187 // Threads are counted via /proc/self/task. This is a little hairy because of | 201 // Threads are counted via /proc/self/task. This is a little hairy because of |
188 // PID namespaces and existing sandboxes, so "self" must really be used instead | 202 // PID namespaces and existing sandboxes, so "self" must really be used instead |
189 // of using the pid. | 203 // of using the pid. |
190 bool LinuxSandbox::IsSingleThreaded() const { | 204 bool LinuxSandbox::IsSingleThreaded() const { |
191 bool is_single_threaded = false; | 205 bool is_single_threaded = false; |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { | 380 void LinuxSandbox::StopThreadAndEnsureNotCounted(base::Thread* thread) const { |
367 DCHECK(thread); | 381 DCHECK(thread); |
368 int proc_self_task = OpenProcTaskFd(proc_fd_); | 382 int proc_self_task = OpenProcTaskFd(proc_fd_); |
369 PCHECK(proc_self_task >= 0); | 383 PCHECK(proc_self_task >= 0); |
370 SafeScopedFD task_closer(&proc_self_task); | 384 SafeScopedFD task_closer(&proc_self_task); |
371 CHECK( | 385 CHECK( |
372 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); | 386 sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_self_task, thread)); |
373 } | 387 } |
374 | 388 |
375 } // namespace content | 389 } // namespace content |
OLD | NEW |