Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1486)

Unified Diff: content/common/sandbox_linux.cc

Issue 24055003: add a LinuxSandbox::HasOpenDirectories() sanity check (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: simply compare fd's Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/common/sandbox_linux.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/sandbox_linux.cc
diff --git a/content/common/sandbox_linux.cc b/content/common/sandbox_linux.cc
index 2ce96b67d4514842c6a5d291a98f0f759751ca0f..a805bd869b0c692996241ffc97c5c48b6a698c72 100644
--- a/content/common/sandbox_linux.cc
+++ b/content/common/sandbox_linux.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <dirent.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/stat.h>
@@ -16,6 +17,7 @@
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "content/common/sandbox_linux.h"
#include "content/common/sandbox_seccomp_bpf_linux.h"
@@ -60,6 +62,12 @@ bool IsRunningTSAN() {
#endif
}
+struct DIRDeleter {
+ void operator()(DIR *d) {
+ CHECK(closedir(d) == 0);
+ }
+};
+
} // namespace
namespace content {
@@ -68,6 +76,7 @@ LinuxSandbox::LinuxSandbox()
: proc_fd_(-1),
seccomp_bpf_started_(false),
pre_initialized_(false),
+ sealed_(false),
seccomp_bpf_supported_(false),
setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
if (setuid_sandbox_client_ == NULL) {
@@ -91,6 +100,7 @@ extern "C" void __sanitizer_sandbox_on_notify(void *reserved);
void LinuxSandbox::PreinitializeSandbox() {
CHECK(!pre_initialized_);
+ CHECK(!sealed_);
seccomp_bpf_supported_ = false;
#if defined(ADDRESS_SANITIZER) && defined(OS_LINUX)
// ASan needs to open some resources before the sandbox is enabled.
@@ -98,12 +108,8 @@ void LinuxSandbox::PreinitializeSandbox() {
__sanitizer_sandbox_on_notify(/*reserved*/NULL);
#endif
-#if !defined(NDEBUG)
- // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't
- // produce a sandbox escape in Release mode.
- proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
- CHECK_GE(proc_fd_, 0);
-#endif // !defined(NDEBUG)
+ OpenProc();
+
// We "pre-warm" the code that detects supports for seccomp BPF.
if (SandboxSeccompBpf::IsSeccompBpfDesired()) {
if (!SandboxSeccompBpf::SupportsSandbox()) {
@@ -118,6 +124,7 @@ void LinuxSandbox::PreinitializeSandbox() {
bool LinuxSandbox::InitializeSandbox() {
bool seccomp_bpf_started = false;
LinuxSandbox* linux_sandbox = LinuxSandbox::GetInstance();
+ CHECK(!linux_sandbox->sealed_);
// We need to make absolutely sure that our sandbox is "sealed" before
// InitializeSandbox does exit.
base::ScopedClosureRunner sandbox_sealer(
@@ -143,6 +150,12 @@ bool LinuxSandbox::InitializeSandbox() {
return false;
}
+ if (linux_sandbox->HasOpenDirectories()) {
+ LOG(FATAL) << "InitializeSandbox() called after unexpected directories "
+ "have been opened- the setuid sandbox may be at risk, if "
+ "the BPF sandbox is not running.";
+ }
+
// Attempt to limit the future size of the address space of the process.
linux_sandbox->LimitAddressSpace(process_type);
@@ -208,6 +221,60 @@ bool LinuxSandbox::IsSingleThreaded() const {
return task_stat.st_nlink == 3;
}
+bool LinuxSandbox::OpenProc() {
jln (very slow on Chromium) 2013/11/01 18:55:37 Please, remove this.
Mostyn Bramley-Moore 2013/11/01 22:22:40 Done.
+ CHECK(!sealed_);
+#if !defined(NDEBUG)
+ if (proc_fd_ == -1) {
+ // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't
+ // produce a sandbox escape in Release mode.
+ proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY);
+ CHECK_GE(proc_fd_, 0);
+ }
+ return true;
+#else
+ return false;
+#endif // !defined(NDEBUG)
+}
+
+bool LinuxSandbox::HasOpenDirectories() {
+ CHECK(!sealed_);
+ if (!OpenProc()) {
jln (very slow on Chromium) 2013/11/01 18:55:37 You don't need to do the OpenProc() thing, it adds
Mostyn Bramley-Moore 2013/11/01 22:22:40 Done- I assume you mean errno == ENOENT ?
+ // We must not be in debug mode, so guess false;
+ return false;
+ }
+
+ int proc_self_fd = openat(proc_fd_, "self/fd", O_RDONLY|O_DIRECTORY);
+ CHECK(proc_self_fd != -1);
+
+ // Ownership of proc_self_fd is transferred here, it must not be closed
+ // or modified afterwards except via dir.
+ DIR *dir = fdopendir(proc_self_fd);
jln (very slow on Chromium) 2013/11/01 18:55:37 Style: I don't like it but the style is T* ptr, no
Mostyn Bramley-Moore 2013/11/01 22:22:40 Done.
+ CHECK(dir);
+ scoped_ptr<DIR, DIRDeleter> dir_fd(dir);
jln (very slow on Chromium) 2013/11/01 18:55:37 Just have directly: scoped_ptr<DIR, DIRDeleter> d
Mostyn Bramley-Moore 2013/11/01 22:22:40 Done.
+
+ struct dirent e, *de;
jln (very slow on Chromium) 2013/11/01 18:55:37 Style: on two different lines Unfortunately the st
Mostyn Bramley-Moore 2013/11/01 22:22:40 Done.
+ while (!readdir_r(dir, &e, &de) && de) {
+ if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0)
+ continue;
+
+ int fd_num;
+ CHECK(base::StringToInt(e.d_name, &fd_num));
+ if (fd_num == proc_fd_ || fd_num == proc_self_fd) {
+ continue;
+ }
+
+ struct stat s;
+ // It's OK to use proc_self_fd here, fstatat won't modify it.
jln (very slow on Chromium) 2013/11/01 18:55:37 Maybe it's more readable with dirfd(dir.get()) ? Y
Mostyn Bramley-Moore 2013/11/01 22:22:40 IMO it's more obvious to people reading this code
+ CHECK(fstatat(proc_self_fd, e.d_name, &s, 0) == 0);
+ if (S_ISDIR(s.st_mode)) {
+ return true;
+ }
+ }
+
+ // No open unmanaged directories found. \o/
+ return false;
+}
+
bool LinuxSandbox::seccomp_bpf_started() const {
return seccomp_bpf_started_;
}
@@ -282,6 +349,7 @@ void LinuxSandbox::SealSandbox() {
CHECK_EQ(0, ret);
proc_fd_ = -1;
}
+ sealed_ = true;
}
} // namespace content
« no previous file with comments | « content/common/sandbox_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698