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

Side by Side Diff: components/nacl/loader/sandbox_linux/nacl_sandbox_linux.cc

Issue 276443003: NaCl: Add sanity check for number of open FDs at startup (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Simplify as suggested in review Created 6 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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>
(...skipping 28 matching lines...) Expand all
39 return true; 39 return true;
40 } 40 }
41 41
42 } // namespace 42 } // namespace
43 43
44 NaClSandbox::NaClSandbox() 44 NaClSandbox::NaClSandbox()
45 : layer_one_enabled_(false), 45 : layer_one_enabled_(false),
46 layer_one_sealed_(false), 46 layer_one_sealed_(false),
47 layer_two_enabled_(false), 47 layer_two_enabled_(false),
48 layer_two_is_nonsfi_(false), 48 layer_two_is_nonsfi_(false),
49 proc_fd_(-1) { 49 proc_fd_(-1),
50 setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()) {
50 proc_fd_.reset( 51 proc_fd_.reset(
51 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC))); 52 HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC)));
52 PCHECK(proc_fd_.is_valid()); 53 PCHECK(proc_fd_.is_valid());
53 } 54 }
54 55
55 NaClSandbox::~NaClSandbox() { 56 NaClSandbox::~NaClSandbox() {
56 } 57 }
57 58
58 bool NaClSandbox::IsSingleThreaded() { 59 bool NaClSandbox::IsSingleThreaded() {
59 CHECK(proc_fd_.is_valid()); 60 CHECK(proc_fd_.is_valid());
60 base::ScopedFD proc_self_task(HANDLE_EINTR(openat( 61 base::ScopedFD proc_self_task(HANDLE_EINTR(openat(
61 proc_fd_.get(), "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC))); 62 proc_fd_.get(), "self/task/", O_RDONLY | O_DIRECTORY | O_CLOEXEC)));
62 PCHECK(proc_self_task.is_valid()); 63 PCHECK(proc_self_task.is_valid());
63 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get()); 64 return sandbox::ThreadHelpers::IsSingleThreaded(proc_self_task.get());
64 } 65 }
65 66
66 bool NaClSandbox::HasOpenDirectory() { 67 bool NaClSandbox::HasOpenDirectory() {
67 CHECK(proc_fd_.is_valid()); 68 CHECK(proc_fd_.is_valid());
68 sandbox::Credentials credentials; 69 sandbox::Credentials credentials;
69 return credentials.HasOpenDirectory(proc_fd_.get()); 70 return credentials.HasOpenDirectory(proc_fd_.get());
70 } 71 }
71 72
72 void NaClSandbox::InitializeLayerOneSandbox() { 73 void NaClSandbox::InitializeLayerOneSandbox() {
73 // Check that IsSandboxed() works. We should not be sandboxed at this point. 74 // Check that IsSandboxed() works. We should not be sandboxed at this point.
74 CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!"; 75 CHECK(!IsSandboxed()) << "Unexpectedly sandboxed!";
75 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client(
76 sandbox::SetuidSandboxClient::Create());
77 const bool suid_sandbox_child = setuid_sandbox_client->IsSuidSandboxChild();
78 76
79 if (suid_sandbox_child) { 77 if (setuid_sandbox_client_->IsSuidSandboxChild()) {
80 setuid_sandbox_client->CloseDummyFile(); 78 setuid_sandbox_client_->CloseDummyFile();
81 79
82 // Make sure that no directory file descriptor is open, as it would bypass 80 // Make sure that no directory file descriptor is open, as it would bypass
83 // the setuid sandbox model. 81 // the setuid sandbox model.
84 CHECK(!HasOpenDirectory()); 82 CHECK(!HasOpenDirectory());
85 83
86 // Get sandboxed. 84 // Get sandboxed.
87 CHECK(setuid_sandbox_client->ChrootMe()); 85 CHECK(setuid_sandbox_client_->ChrootMe());
88 CHECK(IsSandboxed()); 86 CHECK(IsSandboxed());
89 layer_one_enabled_ = true; 87 layer_one_enabled_ = true;
90 } 88 }
91 } 89 }
92 90
91 void NaClSandbox::CheckForExpectedNumberOfOpenFds() {
92 if (setuid_sandbox_client_->IsSuidSandboxChild()) {
93 // We expect to have the following FDs open:
94 // 1-3) stdin, stdout, stderr.
95 // 4) The /dev/urandom FD used by base::GetUrandomFD().
96 // 5) A dummy pipe FD used to overwrite kSandboxIPCChannel.
97 // 6) The socket created by the SUID sandbox helper, used by ChrootMe().
98 // After ChrootMe(), this is no longer connected to anything.
99 // (Only present when running under the SUID sandbox.)
100 // 7) The socket for the Chrome IPC channel that's connected to the
101 // browser process, kPrimaryIPCChannel.
102 //
103 // This sanity check ensures that dynamically loaded libraries don't
104 // leave any FDs open before we enable the sandbox.
105 sandbox::Credentials credentials;
106 CHECK_EQ(7, credentials.CountOpenFds(proc_fd_.get()));
107 }
108 }
109
93 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) { 110 void NaClSandbox::InitializeLayerTwoSandbox(bool uses_nonsfi_mode) {
94 // seccomp-bpf only applies to the current thread, so it's critical to only 111 // seccomp-bpf only applies to the current thread, so it's critical to only
95 // have a single thread running here. 112 // have a single thread running here.
96 DCHECK(!layer_one_sealed_); 113 DCHECK(!layer_one_sealed_);
97 CHECK(IsSingleThreaded()); 114 CHECK(IsSingleThreaded());
115 CheckForExpectedNumberOfOpenFds();
116
98 if (uses_nonsfi_mode) { 117 if (uses_nonsfi_mode) {
99 layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox(); 118 layer_two_enabled_ = nacl::nonsfi::InitializeBPFSandbox();
100 layer_two_is_nonsfi_ = true; 119 layer_two_is_nonsfi_ = true;
101 } else { 120 } else {
102 layer_two_enabled_ = nacl::InitializeBPFSandbox(); 121 layer_two_enabled_ = nacl::InitializeBPFSandbox();
103 } 122 }
104 } 123 }
105 124
106 void NaClSandbox::SealLayerOneSandbox() { 125 void NaClSandbox::SealLayerOneSandbox() {
107 if (!layer_two_enabled_) { 126 if (!layer_two_enabled_) {
(...skipping 29 matching lines...) Expand all
137 static const char kNoBpfMsg[] = 156 static const char kNoBpfMsg[] =
138 "The seccomp-bpf sandbox is not engaged for NaCl:"; 157 "The seccomp-bpf sandbox is not engaged for NaCl:";
139 if (can_be_no_sandbox) 158 if (can_be_no_sandbox)
140 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg; 159 LOG(ERROR) << kNoBpfMsg << kItIsDangerousMsg;
141 else 160 else
142 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg; 161 LOG(FATAL) << kNoBpfMsg << kItIsNotAllowedMsg;
143 } 162 }
144 } 163 }
145 164
146 } // namespace nacl 165 } // namespace nacl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698