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 "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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |