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/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 // in file name limit error-handling-code-paths, etc. | 31 // in file name limit error-handling-code-paths, etc. |
32 const size_t kMaxFileLength = 40; | 32 const size_t kMaxFileLength = 40; |
33 | 33 |
34 void NotifyRendererOfError( | 34 void NotifyRendererOfError( |
35 nacl::NaClHostMessageFilter* nacl_host_message_filter, | 35 nacl::NaClHostMessageFilter* nacl_host_message_filter, |
36 IPC::Message* reply_msg) { | 36 IPC::Message* reply_msg) { |
37 reply_msg->set_reply_error(); | 37 reply_msg->set_reply_error(); |
38 nacl_host_message_filter->Send(reply_msg); | 38 nacl_host_message_filter->Send(reply_msg); |
39 } | 39 } |
40 | 40 |
41 base::File PnaclDoOpenFile(const base::FilePath& file_to_open) { | 41 typedef void (*WriteFileInfoReply)(IPC::Message* reply_msg, |
42 return base::File(file_to_open, | 42 IPC::PlatformFileForTransit file_desc, |
43 base::File::FLAG_OPEN | base::File::FLAG_READ); | 43 uint64 file_token_lo, |
44 uint64 file_token_hi); | |
45 | |
46 void DoRegisterOpenedNaClExecutableFile( | |
47 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, | |
48 base::File file, | |
49 base::FilePath file_path, | |
50 IPC::Message* reply_msg, | |
51 WriteFileInfoReply write_reply_message) { | |
52 // IO thread owns the NaClBrowser singleton. | |
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
54 | |
55 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | |
56 uint64 file_token_lo = 0; | |
57 uint64 file_token_hi = 0; | |
58 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); | |
59 | |
60 IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess( | |
61 file.Pass(), | |
62 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); | |
44 } | 66 } |
45 | 67 |
46 void DoOpenPnaclFile( | 68 void DoOpenPnaclFile( |
47 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, | 69 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, |
48 const std::string& filename, | 70 const std::string& filename, |
71 bool is_executable, | |
49 IPC::Message* reply_msg) { | 72 IPC::Message* reply_msg) { |
50 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 73 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
51 base::FilePath full_filepath; | 74 base::FilePath full_filepath; |
52 | 75 |
53 // PNaCl must be installed. | 76 // PNaCl must be installed. |
54 base::FilePath pnacl_dir; | 77 base::FilePath pnacl_dir; |
55 if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) || | 78 if (!nacl::NaClBrowser::GetDelegate()->GetPnaclDirectory(&pnacl_dir) || |
56 !base::PathExists(pnacl_dir)) { | 79 !base::PathExists(pnacl_dir)) { |
57 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 80 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
58 return; | 81 return; |
59 } | 82 } |
60 | 83 |
61 // Do some validation. | 84 // Do some validation. |
62 if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) { | 85 if (!nacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) { |
63 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 86 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
64 return; | 87 return; |
65 } | 88 } |
66 | 89 |
67 base::File file_to_open = PnaclDoOpenFile(full_filepath); | 90 base::File file_to_open = nacl::OpenNaClReadExecImpl(full_filepath, |
91 is_executable); | |
68 if (!file_to_open.IsValid()) { | 92 if (!file_to_open.IsValid()) { |
69 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 93 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
70 return; | 94 return; |
71 } | 95 } |
72 | 96 |
73 // Send the reply! | 97 // This function is running on the blocking pool, but the path needs to be |
74 // Do any DuplicateHandle magic that is necessary first. | 98 // registered in a structure owned by the IO thread. |
75 IPC::PlatformFileForTransit target_desc = | 99 // Not all PNaCl files are executable. Only register those that are |
76 IPC::TakeFileHandleForProcess(file_to_open.Pass(), | 100 // executable in the NaCl file_path cache. |
77 nacl_host_message_filter->PeerHandle()); | 101 if (is_executable) { |
78 if (target_desc == IPC::InvalidPlatformFileForTransit()) { | 102 BrowserThread::PostTask( |
79 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 103 BrowserThread::IO, FROM_HERE, |
80 return; | 104 base::Bind(&DoRegisterOpenedNaClExecutableFile, |
105 nacl_host_message_filter, | |
106 Passed(file_to_open.Pass()), full_filepath, reply_msg, | |
107 static_cast<WriteFileInfoReply>( | |
108 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams))); | |
109 } else { | |
110 IPC::PlatformFileForTransit target_desc = | |
111 IPC::TakeFileHandleForProcess(file_to_open.Pass(), | |
112 nacl_host_message_filter->PeerHandle()); | |
113 uint64_t dummy_file_token = 0; | |
114 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams( | |
115 reply_msg, target_desc, dummy_file_token, dummy_file_token); | |
116 nacl_host_message_filter->Send(reply_msg); | |
81 } | 117 } |
82 NaClHostMsg_GetReadonlyPnaclFD::WriteReplyParams( | |
83 reply_msg, target_desc); | |
84 nacl_host_message_filter->Send(reply_msg); | |
85 } | |
86 | |
87 void DoRegisterOpenedNaClExecutableFile( | |
88 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, | |
89 base::File file, | |
90 base::FilePath file_path, | |
91 IPC::Message* reply_msg) { | |
92 // IO thread owns the NaClBrowser singleton. | |
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
94 | |
95 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance(); | |
96 uint64 file_token_lo = 0; | |
97 uint64 file_token_hi = 0; | |
98 nacl_browser->PutFilePath(file_path, &file_token_lo, &file_token_hi); | |
99 | |
100 IPC::PlatformFileForTransit file_desc = IPC::TakeFileHandleForProcess( | |
101 file.Pass(), | |
102 nacl_host_message_filter->PeerHandle()); | |
103 | |
104 NaClHostMsg_OpenNaClExecutable::WriteReplyParams( | |
105 reply_msg, file_desc, file_token_lo, file_token_hi); | |
106 nacl_host_message_filter->Send(reply_msg); | |
107 } | 118 } |
108 | 119 |
109 // Convert the file URL into a file descriptor. | 120 // Convert the file URL into a file descriptor. |
110 // This function is security sensitive. Be sure to check with a security | 121 // This function is security sensitive. Be sure to check with a security |
111 // person before you modify it. | 122 // person before you modify it. |
112 void DoOpenNaClExecutableOnThreadPool( | 123 void DoOpenNaClExecutableOnThreadPool( |
113 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, | 124 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, |
114 const GURL& file_url, | 125 const GURL& file_url, |
115 IPC::Message* reply_msg) { | 126 IPC::Message* reply_msg) { |
116 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 127 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
117 | 128 |
118 base::FilePath file_path; | 129 base::FilePath file_path; |
119 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( | 130 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( |
120 file_url, | 131 file_url, |
121 true /* use_blocking_api */, | 132 true /* use_blocking_api */, |
122 nacl_host_message_filter->profile_directory(), | 133 nacl_host_message_filter->profile_directory(), |
123 &file_path)) { | 134 &file_path)) { |
124 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 135 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
125 return; | 136 return; |
126 } | 137 } |
127 | 138 |
128 base::File file = nacl::OpenNaClExecutableImpl(file_path); | 139 base::File file = nacl::OpenNaClReadExecImpl(file_path, |
140 true /* is_executable */); | |
129 if (file.IsValid()) { | 141 if (file.IsValid()) { |
130 // This function is running on the blocking pool, but the path needs to be | 142 // This function is running on the blocking pool, but the path needs to be |
131 // registered in a structure owned by the IO thread. | 143 // registered in a structure owned by the IO thread. |
132 BrowserThread::PostTask( | 144 BrowserThread::PostTask( |
133 BrowserThread::IO, FROM_HERE, | 145 BrowserThread::IO, FROM_HERE, |
134 base::Bind( | 146 base::Bind( |
135 &DoRegisterOpenedNaClExecutableFile, | 147 &DoRegisterOpenedNaClExecutableFile, |
136 nacl_host_message_filter, | 148 nacl_host_message_filter, |
137 Passed(file.Pass()), file_path, reply_msg)); | 149 Passed(file.Pass()), file_path, reply_msg, |
150 static_cast<WriteFileInfoReply>( | |
151 NaClHostMsg_OpenNaClExecutable::WriteReplyParams))); | |
138 } else { | 152 } else { |
139 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 153 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
140 return; | 154 return; |
141 } | 155 } |
142 } | 156 } |
143 | 157 |
144 } // namespace | 158 } // namespace |
145 | 159 |
146 namespace nacl_file_host { | 160 namespace nacl_file_host { |
147 | 161 |
148 void GetReadonlyPnaclFd( | 162 void GetReadonlyPnaclFd( |
149 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, | 163 scoped_refptr<nacl::NaClHostMessageFilter> nacl_host_message_filter, |
150 const std::string& filename, | 164 const std::string& filename, |
165 bool is_executable, | |
151 IPC::Message* reply_msg) { | 166 IPC::Message* reply_msg) { |
152 if (!BrowserThread::PostBlockingPoolTask( | 167 if (!BrowserThread::PostBlockingPoolTask( |
153 FROM_HERE, | 168 FROM_HERE, |
154 base::Bind(&DoOpenPnaclFile, | 169 base::Bind(&DoOpenPnaclFile, |
155 nacl_host_message_filter, | 170 nacl_host_message_filter, |
156 filename, | 171 filename, |
172 is_executable, | |
157 reply_msg))) { | 173 reply_msg))) { |
158 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 174 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
159 } | 175 } |
160 } | 176 } |
161 | 177 |
162 // This function is security sensitive. Be sure to check with a security | 178 // This function is security sensitive. Be sure to check with a security |
163 // person before you modify it. | 179 // person before you modify it. |
164 bool PnaclCanOpenFile(const std::string& filename, | 180 bool PnaclCanOpenFile(const std::string& filename, |
jvoung (off chromium)
2014/06/27 22:46:28
This attempts to only allow the file to have a-z,
| |
165 base::FilePath* file_to_open) { | 181 base::FilePath* file_to_open) { |
166 if (filename.length() > kMaxFileLength) | 182 if (filename.length() > kMaxFileLength) |
167 return false; | 183 return false; |
168 | 184 |
169 if (filename.empty()) | 185 if (filename.empty()) |
170 return false; | 186 return false; |
171 | 187 |
172 // Restrict character set of the file name to something really simple | 188 // Restrict character set of the file name to something really simple |
173 // (a-z, 0-9, and underscores). | 189 // (a-z, 0-9, and underscores). |
174 for (size_t i = 0; i < filename.length(); ++i) { | 190 for (size_t i = 0; i < filename.length(); ++i) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 FROM_HERE, | 247 FROM_HERE, |
232 base::Bind( | 248 base::Bind( |
233 &DoOpenNaClExecutableOnThreadPool, | 249 &DoOpenNaClExecutableOnThreadPool, |
234 nacl_host_message_filter, | 250 nacl_host_message_filter, |
235 file_url, reply_msg))) { | 251 file_url, reply_msg))) { |
236 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); | 252 NotifyRendererOfError(nacl_host_message_filter.get(), reply_msg); |
237 } | 253 } |
238 } | 254 } |
239 | 255 |
240 } // namespace nacl_file_host | 256 } // namespace nacl_file_host |
OLD | NEW |