OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/nacl_host/pnacl_file_host.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/file_path.h" | |
9 #include "base/file_util.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/path_service.h" | |
12 #include "base/platform_file.h" | |
13 #include "base/utf_string_conversions.h" | |
14 #include "chrome/common/chrome_paths.h" | |
15 #include "chrome/common/render_messages.h" | |
16 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | |
17 #include "content/public/browser/browser_thread.h" | |
18 #include "ipc/ipc_platform_file.h" | |
19 | |
20 using content::BrowserThread; | |
21 | |
22 namespace { | |
23 | |
24 void NotifyRendererOfError( | |
25 ChromeRenderMessageFilter* chrome_render_message_filter, | |
26 IPC::Message* reply_msg) { | |
27 reply_msg->set_reply_error(); | |
28 chrome_render_message_filter->Send(reply_msg); | |
29 } | |
30 | |
31 bool PnaclDoOpenFile(const FilePath& file_to_open, | |
32 base::PlatformFile* out_file) { | |
33 base::PlatformFileError error_code; | |
34 *out_file = base::CreatePlatformFile(file_to_open, | |
35 base::PLATFORM_FILE_OPEN | | |
36 base::PLATFORM_FILE_READ, | |
37 NULL, | |
38 &error_code); | |
39 if (error_code != base::PLATFORM_FILE_OK) { | |
40 return false; | |
41 } | |
42 return true; | |
43 } | |
44 | |
45 void DoOpenPnaclFile( | |
46 ChromeRenderMessageFilter* chrome_render_message_filter, | |
47 std::string filename, | |
brettw
2012/07/12 19:55:16
Nit: const string&
jvoung (off chromium)
2012/07/12 23:06:09
I wasn't sure if it was okay to use "&" in combina
| |
48 IPC::Message* reply_msg) { | |
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
50 FilePath full_filepath; | |
51 | |
52 // Do some validation. | |
53 if (!pnacl_file_host::PnaclCanOpenFile(filename, &full_filepath)) { | |
54 NotifyRendererOfError(chrome_render_message_filter, reply_msg); | |
55 return; | |
56 } | |
57 | |
58 base::PlatformFile file_to_open; | |
59 if (!PnaclDoOpenFile(full_filepath, &file_to_open)) { | |
60 NotifyRendererOfError(chrome_render_message_filter, reply_msg); | |
61 return; | |
62 } | |
63 | |
64 // Send the reply! | |
65 // Do any DuplicateHandle magic that is necessary first. | |
66 IPC::PlatformFileForTransit target_desc = | |
67 IPC::GetFileHandleForProcess(file_to_open, | |
68 chrome_render_message_filter->peer_handle(), | |
69 true /* Close source */); | |
70 if (target_desc == IPC::InvalidPlatformFileForTransit()) { | |
71 NotifyRendererOfError(chrome_render_message_filter, reply_msg); | |
72 return; | |
73 } | |
74 ChromeViewHostMsg_GetReadonlyPnaclFD::WriteReplyParams( | |
75 reply_msg, target_desc); | |
76 chrome_render_message_filter->Send(reply_msg); | |
77 } | |
78 | |
79 } // namespace | |
80 | |
81 namespace pnacl_file_host { | |
82 | |
83 void GetReadonlyPnaclFd( | |
84 ChromeRenderMessageFilter* chrome_render_message_filter, | |
85 const std::string& filename, | |
86 IPC::Message* reply_msg) { | |
87 if (!BrowserThread::PostTask( | |
88 BrowserThread::FILE, FROM_HERE, | |
89 base::Bind(&DoOpenPnaclFile, | |
90 make_scoped_refptr(chrome_render_message_filter), | |
91 filename, | |
92 reply_msg))) { | |
93 NotifyRendererOfError(chrome_render_message_filter, reply_msg); | |
94 } | |
95 } | |
96 | |
97 bool PnaclCanOpenFile(const std::string& filename, | |
98 FilePath *file_to_open) { | |
99 // Do *some* validation, even though this should only be used | |
brettw
2012/07/12 19:55:16
Actually we need to validate very carefully. This
jvoung (off chromium)
2012/07/12 23:06:09
Ah, that's right -- removed comment.
| |
100 // by trusted code... | |
101 | |
102 // The file must use only ASCII characters. | |
103 if (!IsStringASCII(filename)) { | |
104 return false; | |
105 } | |
106 | |
107 // Disallow special shell characters, just in case... | |
108 if (filename.find('%') != std::string::npos || | |
109 filename.find('$') != std::string::npos) { | |
110 return false; | |
111 } | |
112 | |
113 #if defined(OS_WIN) | |
114 FilePath file_to_find(ASCIIToUTF16(filename)); | |
115 #elif defined(OS_POSIX) | |
116 FilePath file_to_find(filename); | |
117 #endif | |
118 | |
119 if (file_to_find.empty() || file_util::IsDot(file_to_find)) { | |
120 return false; | |
121 } | |
122 | |
123 // Disallow peeking outside of the pnacl component directory. | |
124 if (file_to_find.ReferencesParent() || file_to_find.IsAbsolute()) { | |
125 return false; | |
126 } | |
127 | |
128 FilePath pnacl_dir; | |
129 if (!PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_dir)) { | |
130 return false; | |
131 } | |
132 if (pnacl_dir.empty()) { | |
133 return false; | |
134 } | |
135 | |
136 FilePath full_path = pnacl_dir.Append(file_to_find); | |
137 *file_to_open = full_path; | |
138 return true; | |
139 } | |
140 | |
141 } // namespace pnacl_file_host | |
OLD | NEW |