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

Side by Side Diff: components/nacl/browser/nacl_file_host.cc

Issue 649603004: Non-SFI NaCl: Batch-open resource files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: code review Created 6 years, 1 month 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
OLDNEW
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 "components/nacl/browser/nacl_file_host.h" 5 #include "components/nacl/browser/nacl_file_host.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/files/file.h" 8 #include "base/files/file.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/threading/sequenced_worker_pool.h" 13 #include "base/threading/sequenced_worker_pool.h"
14 #include "components/nacl/browser/nacl_browser.h" 14 #include "components/nacl/browser/nacl_browser.h"
15 #include "components/nacl/browser/nacl_browser_delegate.h" 15 #include "components/nacl/browser/nacl_browser_delegate.h"
16 #include "components/nacl/browser/nacl_host_message_filter.h" 16 #include "components/nacl/browser/nacl_host_message_filter.h"
17 #include "components/nacl/common/nacl_host_messages.h" 17 #include "components/nacl/common/nacl_host_messages.h"
18 #include "components/nacl/common/nacl_types.h"
18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/render_view_host.h" 20 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/site_instance.h" 21 #include "content/public/browser/site_instance.h"
21 #include "ipc/ipc_platform_file.h" 22 #include "ipc/ipc_platform_file.h"
22 23
23 using content::BrowserThread; 24 using content::BrowserThread;
24 25
25 namespace { 26 namespace {
26 27
27 // Force a prefix to prevent user from opening "magic" files. 28 // Force a prefix to prevent user from opening "magic" files.
28 const char* kExpectedFilePrefix = "pnacl_public_"; 29 const char* kExpectedFilePrefix = "pnacl_public_";
29 30
30 // Restrict PNaCl file lengths to reduce likelyhood of hitting bugs 31 // Restrict PNaCl file lengths to reduce likelyhood of hitting bugs
31 // in file name limit error-handling-code-paths, etc. 32 // in file name limit error-handling-code-paths, etc.
32 const size_t kMaxFileLength = 40; 33 const size_t kMaxFileLength = 40;
33 34
34 void NotifyRendererOfError( 35 void NotifyRendererOfError(
35 nacl::NaClHostMessageFilter* nacl_host_message_filter, 36 nacl::NaClHostMessageFilter* nacl_host_message_filter,
36 IPC::Message* reply_msg) { 37 IPC::Message* reply_msg) {
37 reply_msg->set_reply_error(); 38 reply_msg->set_reply_error();
38 nacl_host_message_filter->Send(reply_msg); 39 nacl_host_message_filter->Send(reply_msg);
39 } 40 }
40 41
42 typedef void (*WriteFileInfoReplyPnacl)(IPC::Message* reply_msg,
43 IPC::PlatformFileForTransit file_desc,
44 uint64 file_token_lo,
45 uint64 file_token_hi);
46
47 void DoRegisterOpenedNaClExecutableFilePnacl(
48 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
49 base::File file,
50 base::FilePath file_path,
51 IPC::Message* reply_msg,
52 WriteFileInfoReplyPnacl write_reply_message) {
53 // IO thread owns the NaClBrowser singleton.
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
55
56 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
57 uint64 file_token_lo = 0;
58 uint64 file_token_hi = 0;
59 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi);
60
61 IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess(
62 file.Pass(), nacl_host_message_filter->PeerHandle());
63
64 write_reply_message(reply_msg, file_desc, file_token_lo, file_token_hi);
65 nacl_host_message_filter->Send(reply_msg);
66 }
67
41 typedef void (*WriteFileInfoReply)(IPC::Message* reply_msg, 68 typedef void (*WriteFileInfoReply)(IPC::Message* reply_msg,
42 IPC::PlatformFileForTransit file_desc, 69 nacl::NaClOpenExecutableResult open_result);
43 uint64 file_token_lo,
44 uint64 file_token_hi);
45 70
46 void DoRegisterOpenedNaClExecutableFile( 71 void DoRegisterOpenedNaClExecutableFile(
47 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 72 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
48 base::File file, 73 base::File file,
49 base::FilePath file_path, 74 base::FilePath file_path,
75 scoped_ptr<base::File[]> resource_files,
76 const std::vector<base::FilePath>& resource_file_paths,
50 IPC::Message* reply_msg, 77 IPC::Message* reply_msg,
51 WriteFileInfoReply write_reply_message) { 78 WriteFileInfoReply write_reply_message) {
52 // IO thread owns the NaClBrowser singleton. 79 // IO thread owns the NaClBrowser singleton.
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
54 81
55 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); 82 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
56 uint64 file_token_lo = 0; 83 uint64 file_token_lo = 0;
57 uint64 file_token_hi = 0; 84 uint64 file_token_hi = 0;
58 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); 85 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi);
59 86
60 IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess( 87 IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess(
61 file.Pass(), 88 file.Pass(),
62 nacl_host_message_filter->PeerHandle()); 89 nacl_host_message_filter->PeerHandle());
63 90
64 write_reply_message(reply_msg, file_desc, file_token_lo, file_token_hi); 91 std::vector<IPC::PlatformFileForTransit> resource_file_handles;
92 std::vector<std::pair<uint64, uint64> > resource_file_tokens;
teravest 2014/10/24 16:18:06 Why are you using a pair of uint64 here instead of
Yusuke Sato 2014/11/04 22:50:21 Stopped using a pair and switched to a struct foll
93 for (size_t i = 0; i < resource_file_paths.size(); ++i) {
94 uint64 resource_file_token_lo = 0;
95 uint64 resource_file_token_hi = 0;
96 nacl_browser->PutFilePath(resource_file_paths[i],
97 &resource_file_token_lo,
98 &resource_file_token_hi);
99 resource_file_handles.push_back(IPC::TakeFileHandleForProcess(
100 resource_files[i].Pass(), nacl_host_message_filter->PeerHandle()));
101 resource_file_tokens.push_back(std::make_pair(resource_file_token_lo,
102 resource_file_token_hi));
103 }
104
105 write_reply_message(reply_msg,
106 nacl::NaClOpenExecutableResult(file_desc,
107 file_token_lo,
108 file_token_hi,
109 resource_file_handles,
110 resource_file_tokens));
65 nacl_host_message_filter->Send(reply_msg); 111 nacl_host_message_filter->Send(reply_msg);
66 } 112 }
67 113
68 void DoOpenPnaclFile( 114 void DoOpenPnaclFile(
69 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 115 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
70 const std::string& filename, 116 const std::string& filename,
71 bool is_executable, 117 bool is_executable,
72 IPC::Message* reply_msg) { 118 IPC::Message* reply_msg) {
73 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 119 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
74 base::FilePath full_filepath; 120 base::FilePath full_filepath;
(...skipping 19 matching lines...) Expand all
94 return; 140 return;
95 } 141 }
96 142
97 // This function is running on the blocking pool, but the path needs to be 143 // This function is running on the blocking pool, but the path needs to be
98 // registered in a structure owned by the IO thread. 144 // registered in a structure owned by the IO thread.
99 // Not all PNaCl files are executable. Only register those that are 145 // Not all PNaCl files are executable. Only register those that are
100 // executable in the NaCl file_path cache. 146 // executable in the NaCl file_path cache.
101 if (is_executable) { 147 if (is_executable) {
102 BrowserThread::PostTask( 148 BrowserThread::PostTask(
103 BrowserThread::IO, FROM_HERE, 149 BrowserThread::IO, FROM_HERE,
104 base::Bind(&DoRegisterOpenedNaClExecutableFile, 150 base::Bind(&DoRegisterOpenedNaClExecutableFilePnacl,
105 nacl_host_message_filter, 151 nacl_host_message_filter,
106 Passed(file_to_open.Pass()), full_filepath, reply_msg, 152 Passed(file_to_open.Pass()), full_filepath, reply_msg,
107 static_cast<WriteFileInfoReply>( 153 static_cast<WriteFileInfoReplyPnacl>(
108 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams))); 154 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams)));
109 } else { 155 } else {
110 IPC::PlatformFileForTransit target_desc = 156 IPC::PlatformFileForTransit target_desc =
111 IPC::TakeFileHandleForProcess(file_to_open.Pass(), 157 IPC::TakeFileHandleForProcess(file_to_open.Pass(),
112 nacl_host_message_filter->PeerHandle()); 158 nacl_host_message_filter->PeerHandle());
113 uint64_t dummy_file_token = 0; 159 uint64_t dummy_file_token = 0;
114 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams( 160 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams(
115 reply_msg, target_desc, dummy_file_token, dummy_file_token); 161 reply_msg, target_desc, dummy_file_token, dummy_file_token);
116 nacl_host_message_filter->Send(reply_msg); 162 nacl_host_message_filter->Send(reply_msg);
117 } 163 }
118 } 164 }
119 165
120 // Convert the file URL into a file descriptor. 166 // Convert the file URL into a file descriptor.
121 // This function is security sensitive. Be sure to check with a security 167 // This function is security sensitive. Be sure to check with a security
122 // person before you modify it. 168 // person before you modify it.
123 void DoOpenNaClExecutableOnThreadPool( 169 void DoOpenNaClExecutableOnThreadPool(
124 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 170 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
125 const GURL& file_url, 171 const GURL& file_url,
172 const std::vector<GURL>& resource_urls,
126 IPC::Message* reply_msg) { 173 IPC::Message* reply_msg) {
127 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 174 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
128 175
129 base::FilePath file_path; 176 base::FilePath file_path;
130 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( 177 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath(
131 file_url, 178 file_url,
132 true /* use_blocking_api */, 179 true /* use_blocking_api */,
133 nacl_host_message_filter->profile_directory(), 180 nacl_host_message_filter->profile_directory(),
134 &file_path)) { 181 &file_path)) {
135 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 182 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
136 return; 183 return;
137 } 184 }
138 185
139 base::File file = nacl::OpenNaClReadExecImpl(file_path, 186 base::File file = nacl::OpenNaClReadExecImpl(file_path,
140 true /* is_executable */); 187 true /* is_executable */);
141 if (file.IsValid()) { 188 if (!file.IsValid()) {
142 // This function is running on the blocking pool, but the path needs to be
143 // registered in a structure owned by the IO thread.
144 BrowserThread::PostTask(
145 BrowserThread::IO, FROM_HERE,
146 base::Bind(
147 &DoRegisterOpenedNaClExecutableFile,
148 nacl_host_message_filter,
149 Passed(file.Pass()), file_path, reply_msg,
150 static_cast<WriteFileInfoReply>(
151 NaClHostMsg_OpenNaClExecutable::WriteReplyParams)));
152 } else {
153 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 189 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
154 return; 190 return;
155 } 191 }
192
193 scoped_ptr<base::File[]> resource_files;
teravest 2014/10/24 16:18:05 nit: Why not just do the following? scoped_ptr<b
Yusuke Sato 2014/11/04 22:50:21 This is because resource_urls can be empty (eg. wh
194 if (!resource_urls.empty())
195 resource_files.reset(new base::File[resource_urls.size()]);
196 std::vector<base::FilePath> resource_file_paths(resource_urls.size());
197
198 for (size_t i = 0; i < resource_urls.size(); ++i) {
199 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath(
200 resource_urls[i],
201 true /* use_blocking_api */,
202 nacl_host_message_filter->profile_directory(),
203 &resource_file_paths[i])) {
204 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
205 return;
206 }
207 resource_files[i] = nacl::OpenNaClReadExecImpl(resource_file_paths[i],
208 true /* is_executable */);
209 if (!resource_files[i].IsValid()) {
210 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
211 return;
212 }
213 }
214
215 // This function is running on the blocking pool, but the path needs to be
216 // registered in a structure owned by the IO thread.
217 BrowserThread::PostTask(
218 BrowserThread::IO,
219 FROM_HERE,
220 base::Bind(&DoRegisterOpenedNaClExecutableFile,
221 nacl_host_message_filter,
222 Passed(file.Pass()),
223 file_path,
224 Passed(resource_files.Pass()),
225 resource_file_paths,
226 reply_msg,
227 static_cast<WriteFileInfoReply>(
228 NaClHostMsg_OpenNaClExecutable::WriteReplyParams)));
156 } 229 }
157 230
158 } // namespace 231 } // namespace
159 232
160 namespace nacl_file_host { 233 namespace nacl_file_host {
161 234
162 void GetReadonlyPnaclFd( 235 void GetReadonlyPnaclFd(
163 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 236 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
164 const std::string& filename, 237 const std::string& filename,
165 bool is_executable, 238 bool is_executable,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 base::FilePath full_path = pnacl_dir.AppendASCII( 278 base::FilePath full_path = pnacl_dir.AppendASCII(
206 std::string(kExpectedFilePrefix) + filename); 279 std::string(kExpectedFilePrefix) + filename);
207 *file_to_open = full_path; 280 *file_to_open = full_path;
208 return true; 281 return true;
209 } 282 }
210 283
211 void OpenNaClExecutable( 284 void OpenNaClExecutable(
212 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, 285 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter,
213 int render_view_id, 286 int render_view_id,
214 const GURL& file_url, 287 const GURL& file_url,
288 const std::vector<GURL>& resource_urls,
215 IPC::Message* reply_msg) { 289 IPC::Message* reply_msg) {
216 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 290 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
217 BrowserThread::PostTask( 291 BrowserThread::PostTask(
218 BrowserThread::UI, FROM_HERE, 292 BrowserThread::UI, FROM_HERE,
219 base::Bind( 293 base::Bind(
220 &OpenNaClExecutable, 294 &OpenNaClExecutable,
221 nacl_host_message_filter, 295 nacl_host_message_filter,
222 render_view_id, file_url, reply_msg)); 296 render_view_id, file_url, resource_urls, reply_msg));
223 return; 297 return;
224 } 298 }
225 299
226 // Make sure render_view_id is valid and that the URL is a part of the 300 // Make sure render_view_id is valid and that the URL is a part of the
227 // render view's site. Without these checks, apps could probe the extension 301 // render view's site. Without these checks, apps could probe the extension
228 // directory or run NaCl code from other extensions. 302 // directory or run NaCl code from other extensions.
229 content::RenderViewHost* rvh = content::RenderViewHost::FromID( 303 content::RenderViewHost* rvh = content::RenderViewHost::FromID(
230 nacl_host_message_filter->render_process_id(), render_view_id); 304 nacl_host_message_filter->render_process_id(), render_view_id);
231 if (!rvh) { 305 if (!rvh) {
232 nacl_host_message_filter->BadMessageReceived(); // Kill the renderer. 306 nacl_host_message_filter->BadMessageReceived(); // Kill the renderer.
233 return; 307 return;
234 } 308 }
235 content::SiteInstance* site_instance = rvh->GetSiteInstance(); 309 content::SiteInstance* site_instance = rvh->GetSiteInstance();
236 if (!content::SiteInstance::IsSameWebSite(site_instance->GetBrowserContext(), 310 if (!content::SiteInstance::IsSameWebSite(site_instance->GetBrowserContext(),
237 site_instance->GetSiteURL(), 311 site_instance->GetSiteURL(),
238 file_url)) { 312 file_url)) {
239 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 313 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
240 return; 314 return;
241 } 315 }
242 316
317 for (size_t i = 0; i < resource_urls.size(); ++i) {
318 if (!content::SiteInstance::IsSameWebSite(
319 site_instance->GetBrowserContext(),
320 site_instance->GetSiteURL(),
321 resource_urls[i])) {
322 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
323 return;
324 }
325 }
326
243 // The URL is part of the current app. Now query the extension system for the 327 // The URL is part of the current app. Now query the extension system for the
244 // file path and convert that to a file descriptor. This should be done on a 328 // file path and convert that to a file descriptor. This should be done on a
245 // blocking pool thread. 329 // blocking pool thread.
246 if (!BrowserThread::PostBlockingPoolTask( 330 if (!BrowserThread::PostBlockingPoolTask(
247 FROM_HERE, 331 FROM_HERE,
248 base::Bind( 332 base::Bind(
249 &DoOpenNaClExecutableOnThreadPool, 333 &DoOpenNaClExecutableOnThreadPool,
250 nacl_host_message_filter, 334 nacl_host_message_filter,
251 file_url, reply_msg))) { 335 file_url, resource_urls, reply_msg))) {
252 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); 336 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg);
253 } 337 }
254 } 338 }
255 339
256 } // namespace nacl_file_host 340 } // namespace nacl_file_host
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698