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

Side by Side Diff: components/nacl/loader/nacl_helper_linux.cc

Issue 226033002: Ensure seccomp-bpf cannot be silently disabled for non-SFI NaCl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 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 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 // A mini-zygote specifically for Native Client. 5 // A mini-zygote specifically for Native Client.
6 6
7 #include "components/nacl/loader/nacl_helper_linux.h" 7 #include "components/nacl/loader/nacl_helper_linux.h"
8 8
9 #include <errno.h> 9 #include <errno.h>
10 #include <fcntl.h> 10 #include <fcntl.h>
(...skipping 10 matching lines...) Expand all
21 21
22 #include "base/at_exit.h" 22 #include "base/at_exit.h"
23 #include "base/command_line.h" 23 #include "base/command_line.h"
24 #include "base/logging.h" 24 #include "base/logging.h"
25 #include "base/message_loop/message_loop.h" 25 #include "base/message_loop/message_loop.h"
26 #include "base/posix/eintr_wrapper.h" 26 #include "base/posix/eintr_wrapper.h"
27 #include "base/posix/global_descriptors.h" 27 #include "base/posix/global_descriptors.h"
28 #include "base/posix/unix_domain_socket_linux.h" 28 #include "base/posix/unix_domain_socket_linux.h"
29 #include "base/process/kill.h" 29 #include "base/process/kill.h"
30 #include "base/rand_util.h" 30 #include "base/rand_util.h"
31 #include "components/nacl/common/nacl_switches.h"
31 #include "components/nacl/loader/nacl_listener.h" 32 #include "components/nacl/loader/nacl_listener.h"
32 #include "components/nacl/loader/nacl_sandbox_linux.h" 33 #include "components/nacl/loader/nacl_sandbox_linux.h"
33 #include "content/public/common/zygote_fork_delegate_linux.h" 34 #include "content/public/common/zygote_fork_delegate_linux.h"
34 #include "crypto/nss_util.h" 35 #include "crypto/nss_util.h"
35 #include "ipc/ipc_descriptors.h" 36 #include "ipc/ipc_descriptors.h"
36 #include "ipc/ipc_switches.h" 37 #include "ipc/ipc_switches.h"
37 #include "sandbox/linux/services/libc_urandom_override.h" 38 #include "sandbox/linux/services/libc_urandom_override.h"
38 39
39 namespace { 40 namespace {
40 41
41 struct NaClLoaderSystemInfo { 42 struct NaClLoaderSystemInfo {
42 size_t prereserved_sandbox_size; 43 size_t prereserved_sandbox_size;
43 long number_of_cores; 44 long number_of_cores;
44 }; 45 };
45 46
47 // This is a poor man's check on whether we are sandboxed.
48 bool IsSandboxed() {
49 int proc_fd = open("/proc/self/exe", O_RDONLY);
50 if (proc_fd >= 0) {
51 close(proc_fd);
52 return false;
53 }
54 return true;
55 }
56
57 void InitializeSandbox(bool uses_nonsfi_mode) {
58 if (uses_nonsfi_mode) {
59 const bool setuid_sandbox_enabled = IsSandboxed();
60 CHECK(setuid_sandbox_enabled)
61 << "SUID sandbox is mandatory for non-SFI NaCl";
62 // TODO(hamaji): Add a strict seccomp sandbox for non-SFI NaCl.
63 // https://code.google.com/p/chromium/issues/detail?id=359285
64 bool bpf_sandbox_initialized = InitializeBPFSandbox();
65 CHECK(bpf_sandbox_initialized)
66 << "Could not initialize NaCl's second "
67 << "layer sandbox (seccomp-bpf) for non-SFI mode.";
68 } else {
69 bool bpf_sandbox_initialized = InitializeBPFSandbox();
70 if (!bpf_sandbox_initialized) {
71 LOG(ERROR) << "Could not initialize NaCl's second "
72 << "layer sandbox (seccomp-bpf) for SFI mode.";
73 }
74 }
75 }
76
46 // The child must mimic the behavior of zygote_main_linux.cc on the child 77 // The child must mimic the behavior of zygote_main_linux.cc on the child
47 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from 78 // side of the fork. See zygote_main_linux.cc:HandleForkRequest from
48 // if (!child) { 79 // if (!child) {
49 void BecomeNaClLoader(const std::vector<int>& child_fds, 80 void BecomeNaClLoader(const std::vector<int>& child_fds,
50 const NaClLoaderSystemInfo& system_info, 81 const NaClLoaderSystemInfo& system_info,
51 bool uses_nonsfi_mode) { 82 bool uses_nonsfi_mode,
83 bool no_sandbox) {
52 VLOG(1) << "NaCl loader: setting up IPC descriptor"; 84 VLOG(1) << "NaCl loader: setting up IPC descriptor";
53 // don't need zygote FD any more 85 // don't need zygote FD any more
54 if (IGNORE_EINTR(close(kNaClZygoteDescriptor)) != 0) 86 if (IGNORE_EINTR(close(kNaClZygoteDescriptor)) != 0)
55 LOG(ERROR) << "close(kNaClZygoteDescriptor) failed."; 87 LOG(ERROR) << "close(kNaClZygoteDescriptor) failed.";
56 bool sandbox_initialized = InitializeBPFSandbox(); 88 if (!no_sandbox)
57 if (!sandbox_initialized) { 89 InitializeSandbox(uses_nonsfi_mode);
58 LOG(ERROR) << "Could not initialize NaCl's second "
59 << "layer sandbox (seccomp-bpf).";
60 }
61 base::GlobalDescriptors::GetInstance()->Set( 90 base::GlobalDescriptors::GetInstance()->Set(
62 kPrimaryIPCChannel, 91 kPrimaryIPCChannel,
63 child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]); 92 child_fds[content::ZygoteForkDelegate::kBrowserFDIndex]);
64 93
65 base::MessageLoopForIO main_message_loop; 94 base::MessageLoopForIO main_message_loop;
66 NaClListener listener; 95 NaClListener listener;
67 listener.set_uses_nonsfi_mode(uses_nonsfi_mode); 96 listener.set_uses_nonsfi_mode(uses_nonsfi_mode);
68 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size); 97 listener.set_prereserved_sandbox_size(system_info.prereserved_sandbox_size);
69 listener.set_number_of_cores(system_info.number_of_cores); 98 listener.set_number_of_cores(system_info.number_of_cores);
70 listener.Listen(); 99 listener.Listen();
71 _exit(0); 100 _exit(0);
72 } 101 }
73 102
74 // Start the NaCl loader in a child created by the NaCl loader Zygote. 103 // Start the NaCl loader in a child created by the NaCl loader Zygote.
75 void ChildNaClLoaderInit(const std::vector<int>& child_fds, 104 void ChildNaClLoaderInit(const std::vector<int>& child_fds,
76 const NaClLoaderSystemInfo& system_info, 105 const NaClLoaderSystemInfo& system_info,
77 bool uses_nonsfi_mode) { 106 bool uses_nonsfi_mode) {
107 bool no_sandbox = false;
jln (very slow on Chromium) 2014/04/08 22:25:16 This makes for a logic that is way too complicated
hamaji 2014/04/09 00:06:47 Done.
108 if (uses_nonsfi_mode) {
109 no_sandbox = CommandLine::ForCurrentProcess()->HasSwitch(
110 switches::kNaClDangerousNoSandboxNonSfi);
111 if (no_sandbox)
112 LOG(ERROR) << "DANGEROUS: Running non-SFI NaCl without sandbox!";
113 }
114
78 const int parent_fd = child_fds[content::ZygoteForkDelegate::kParentFDIndex]; 115 const int parent_fd = child_fds[content::ZygoteForkDelegate::kParentFDIndex];
79 const int dummy_fd = child_fds[content::ZygoteForkDelegate::kDummyFDIndex]; 116 const int dummy_fd = child_fds[content::ZygoteForkDelegate::kDummyFDIndex];
80 bool validack = false; 117 bool validack = false;
81 const size_t kMaxReadSize = 1024; 118 const size_t kMaxReadSize = 1024;
82 char buffer[kMaxReadSize]; 119 char buffer[kMaxReadSize];
83 // Wait until the parent process has discovered our PID. We 120 // Wait until the parent process has discovered our PID. We
84 // should not fork any child processes (which the seccomp 121 // should not fork any child processes (which the seccomp
85 // sandbox does) until then, because that can interfere with the 122 // sandbox does) until then, because that can interfere with the
86 // parent's discovery of our PID. 123 // parent's discovery of our PID.
87 const int nread = HANDLE_EINTR(read(parent_fd, buffer, kMaxReadSize)); 124 const int nread = HANDLE_EINTR(read(parent_fd, buffer, kMaxReadSize));
(...skipping 11 matching lines...) Expand all
99 switches::kProcessChannelID, 136 switches::kProcessChannelID,
100 std::string(&buffer[len], nread - len)); 137 std::string(&buffer[len], nread - len));
101 validack = true; 138 validack = true;
102 } 139 }
103 } 140 }
104 if (IGNORE_EINTR(close(dummy_fd)) != 0) 141 if (IGNORE_EINTR(close(dummy_fd)) != 0)
105 LOG(ERROR) << "close(dummy_fd) failed"; 142 LOG(ERROR) << "close(dummy_fd) failed";
106 if (IGNORE_EINTR(close(parent_fd)) != 0) 143 if (IGNORE_EINTR(close(parent_fd)) != 0)
107 LOG(ERROR) << "close(parent_fd) failed"; 144 LOG(ERROR) << "close(parent_fd) failed";
108 if (validack) { 145 if (validack) {
109 BecomeNaClLoader(child_fds, system_info, uses_nonsfi_mode); 146 BecomeNaClLoader(child_fds, system_info, uses_nonsfi_mode, no_sandbox);
110 } else { 147 } else {
111 LOG(ERROR) << "Failed to synch with zygote"; 148 LOG(ERROR) << "Failed to synch with zygote";
112 } 149 }
113 _exit(1); 150 _exit(1);
114 } 151 }
115 152
116 // Handle a fork request from the Zygote. 153 // Handle a fork request from the Zygote.
117 // Some of this code was lifted from 154 // Some of this code was lifted from
118 // content/browser/zygote_main_linux.cc:ForkWithRealPid() 155 // content/browser/zygote_main_linux.cc:ForkWithRealPid()
119 bool HandleForkRequest(const std::vector<int>& child_fds, 156 bool HandleForkRequest(const std::vector<int>& child_fds,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 base::TerminationStatus status; 216 base::TerminationStatus status;
180 if (known_dead) 217 if (known_dead)
181 status = base::GetKnownDeadTerminationStatus(child_to_wait, &exit_code); 218 status = base::GetKnownDeadTerminationStatus(child_to_wait, &exit_code);
182 else 219 else
183 status = base::GetTerminationStatus(child_to_wait, &exit_code); 220 status = base::GetTerminationStatus(child_to_wait, &exit_code);
184 output_pickle->WriteInt(static_cast<int>(status)); 221 output_pickle->WriteInt(static_cast<int>(status));
185 output_pickle->WriteInt(exit_code); 222 output_pickle->WriteInt(exit_code);
186 return true; 223 return true;
187 } 224 }
188 225
189 // This is a poor man's check on whether we are sandboxed.
190 bool IsSandboxed() {
191 int proc_fd = open("/proc/self/exe", O_RDONLY);
192 if (proc_fd >= 0) {
193 close(proc_fd);
194 return false;
195 }
196 return true;
197 }
198
199 // Honor a command |command_type|. Eventual command parameters are 226 // Honor a command |command_type|. Eventual command parameters are
200 // available in |input_iter| and eventual file descriptors attached to 227 // available in |input_iter| and eventual file descriptors attached to
201 // the command are in |attached_fds|. 228 // the command are in |attached_fds|.
202 // Reply to the command on |reply_fds|. 229 // Reply to the command on |reply_fds|.
203 bool HonorRequestAndReply(int reply_fd, 230 bool HonorRequestAndReply(int reply_fd,
204 int command_type, 231 int command_type,
205 const std::vector<int>& attached_fds, 232 const std::vector<int>& attached_fds,
206 const NaClLoaderSystemInfo& system_info, 233 const NaClLoaderSystemInfo& system_info,
207 PickleIterator* input_iter) { 234 PickleIterator* input_iter) {
208 Pickle write_pickle; 235 Pickle write_pickle;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 // Now handle requests from the Zygote. 422 // Now handle requests from the Zygote.
396 while (true) { 423 while (true) {
397 bool request_handled = HandleZygoteRequest(kNaClZygoteDescriptor, 424 bool request_handled = HandleZygoteRequest(kNaClZygoteDescriptor,
398 system_info); 425 system_info);
399 // Do not turn this into a CHECK() without thinking about robustness 426 // Do not turn this into a CHECK() without thinking about robustness
400 // against malicious IPC requests. 427 // against malicious IPC requests.
401 DCHECK(request_handled); 428 DCHECK(request_handled);
402 } 429 }
403 NOTREACHED(); 430 NOTREACHED();
404 } 431 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698