OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_function_dispatcher.h" | 5 #include "extensions/browser/extension_function_dispatcher.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/json/json_string_value_serializer.h" | 10 #include "base/json/json_string_value_serializer.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
25 #include "content/public/browser/render_process_host.h" | 25 #include "content/public/browser/render_process_host.h" |
26 #include "content/public/browser/render_process_host_observer.h" | 26 #include "content/public/browser/render_process_host_observer.h" |
27 #include "content/public/browser/render_view_host.h" | 27 #include "content/public/browser/render_view_host.h" |
28 #include "content/public/browser/service_worker_context.h" | 28 #include "content/public/browser/service_worker_context.h" |
29 #include "content/public/browser/user_metrics.h" | 29 #include "content/public/browser/user_metrics.h" |
30 #include "content/public/browser/web_contents.h" | 30 #include "content/public/browser/web_contents.h" |
31 #include "content/public/browser/web_contents_observer.h" | 31 #include "content/public/browser/web_contents_observer.h" |
32 #include "content/public/common/result_codes.h" | 32 #include "content/public/common/result_codes.h" |
33 #include "extensions/browser/api_activity_monitor.h" | 33 #include "extensions/browser/api_activity_monitor.h" |
| 34 #include "extensions/browser/bad_message.h" |
34 #include "extensions/browser/extension_function_registry.h" | 35 #include "extensions/browser/extension_function_registry.h" |
35 #include "extensions/browser/extension_registry.h" | 36 #include "extensions/browser/extension_registry.h" |
36 #include "extensions/browser/extension_system.h" | 37 #include "extensions/browser/extension_system.h" |
37 #include "extensions/browser/extension_util.h" | 38 #include "extensions/browser/extension_util.h" |
38 #include "extensions/browser/extensions_browser_client.h" | 39 #include "extensions/browser/extensions_browser_client.h" |
39 #include "extensions/browser/io_thread_extension_message_filter.h" | 40 #include "extensions/browser/io_thread_extension_message_filter.h" |
40 #include "extensions/browser/process_manager.h" | 41 #include "extensions/browser/process_manager.h" |
41 #include "extensions/browser/process_map.h" | 42 #include "extensions/browser/process_map.h" |
42 #include "extensions/browser/quota_service.h" | 43 #include "extensions/browser/quota_service.h" |
43 #include "extensions/common/constants.h" | 44 #include "extensions/common/constants.h" |
(...skipping 28 matching lines...) Expand all Loading... |
72 | 73 |
73 // Separate copy of ExtensionAPI used for IO thread extension functions. We need | 74 // Separate copy of ExtensionAPI used for IO thread extension functions. We need |
74 // this because ExtensionAPI has mutable data. It should be possible to remove | 75 // this because ExtensionAPI has mutable data. It should be possible to remove |
75 // this once all the extension APIs are updated to the feature system. | 76 // this once all the extension APIs are updated to the feature system. |
76 struct Static { | 77 struct Static { |
77 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} | 78 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} |
78 std::unique_ptr<ExtensionAPI> api; | 79 std::unique_ptr<ExtensionAPI> api; |
79 }; | 80 }; |
80 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; | 81 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; |
81 | 82 |
82 // Kills the specified process because it sends us a malformed message. | 83 void LogBadMessage(functions::HistogramValue histogram_value) { |
83 // Track the specific function's |histogram_value|, as this may indicate a bug | 84 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); |
84 // in that API's implementation on the renderer. | 85 // Track the specific function's |histogram_value|, as this may indicate a |
85 void KillBadMessageSender(const base::Process& process, | 86 // bug in that API's implementation. |
86 functions::HistogramValue histogram_value) { | 87 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", |
| 88 histogram_value, functions::ENUM_BOUNDARY); |
| 89 } |
| 90 |
| 91 template <class T> |
| 92 void ReceivedBadMessage(T* bad_message_sender, |
| 93 bad_message::BadMessageReason reason, |
| 94 functions::HistogramValue histogram_value) { |
| 95 LogBadMessage(histogram_value); |
87 // The renderer has done validation before sending extension api requests. | 96 // The renderer has done validation before sending extension api requests. |
88 // Therefore, we should never receive a request that is invalid in a way | 97 // Therefore, we should never receive a request that is invalid in a way |
89 // that JSON validation in the renderer should have caught. It could be an | 98 // that JSON validation in the renderer should have caught. It could be an |
90 // attacker trying to exploit the browser, so we crash the renderer instead. | 99 // attacker trying to exploit the browser, so we crash the renderer instead. |
91 LOG(ERROR) << "Terminating renderer because of malformed extension message."; | 100 bad_message::ReceivedBadMessage(bad_message_sender, reason); |
92 if (content::RenderProcessHost::run_renderer_in_process()) { | |
93 // In single process mode it is better if we don't suicide but just crash. | |
94 CHECK(false); | |
95 return; | |
96 } | |
97 | |
98 NOTREACHED(); | |
99 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); | |
100 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", | |
101 histogram_value, functions::ENUM_BOUNDARY); | |
102 if (process.IsValid()) | |
103 process.Terminate(content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | |
104 } | 101 } |
105 | 102 |
106 void KillBadMessageSenderRPH(content::RenderProcessHost* sender_process_host, | 103 template <class T> |
107 functions::HistogramValue histogram_value) { | |
108 base::Process peer_process = | |
109 content::RenderProcessHost::run_renderer_in_process() | |
110 ? base::Process::Current() | |
111 : base::Process::DeprecatedGetProcessFromHandle( | |
112 sender_process_host->GetHandle()); | |
113 KillBadMessageSender(peer_process, histogram_value); | |
114 } | |
115 | |
116 void CommonResponseCallback(IPC::Sender* ipc_sender, | 104 void CommonResponseCallback(IPC::Sender* ipc_sender, |
117 int routing_id, | 105 int routing_id, |
118 const base::Process& peer_process, | 106 T* bad_message_sender, |
119 int request_id, | 107 int request_id, |
120 ExtensionFunction::ResponseType type, | 108 ExtensionFunction::ResponseType type, |
121 const base::ListValue& results, | 109 const base::ListValue& results, |
122 const std::string& error, | 110 const std::string& error, |
123 functions::HistogramValue histogram_value) { | 111 functions::HistogramValue histogram_value) { |
124 DCHECK(ipc_sender); | 112 DCHECK(ipc_sender); |
125 | 113 |
126 if (type == ExtensionFunction::BAD_MESSAGE) { | 114 if (type == ExtensionFunction::BAD_MESSAGE) { |
127 KillBadMessageSender(peer_process, histogram_value); | 115 ReceivedBadMessage(bad_message_sender, bad_message::EFD_BAD_MESSAGE, |
| 116 histogram_value); |
128 return; | 117 return; |
129 } | 118 } |
130 | 119 |
131 ipc_sender->Send(new ExtensionMsg_Response( | 120 ipc_sender->Send(new ExtensionMsg_Response( |
132 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, | 121 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, |
133 error)); | 122 error)); |
134 } | 123 } |
135 | 124 |
136 void IOThreadResponseCallback( | 125 void IOThreadResponseCallback( |
137 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, | 126 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, |
138 int routing_id, | 127 int routing_id, |
139 int request_id, | 128 int request_id, |
140 ExtensionFunction::ResponseType type, | 129 ExtensionFunction::ResponseType type, |
141 const base::ListValue& results, | 130 const base::ListValue& results, |
142 const std::string& error, | 131 const std::string& error, |
143 functions::HistogramValue histogram_value) { | 132 functions::HistogramValue histogram_value) { |
144 if (!ipc_sender.get()) | 133 if (!ipc_sender.get()) |
145 return; | 134 return; |
146 | 135 |
147 base::Process peer_process = | 136 CommonResponseCallback(ipc_sender.get(), routing_id, ipc_sender.get(), |
148 base::Process::DeprecatedGetProcessFromHandle(ipc_sender->PeerHandle()); | 137 request_id, type, results, error, histogram_value); |
149 CommonResponseCallback(ipc_sender.get(), routing_id, peer_process, request_id, | |
150 type, results, error, histogram_value); | |
151 } | 138 } |
152 | 139 |
153 } // namespace | 140 } // namespace |
154 | 141 |
155 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper | 142 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper |
156 : public content::WebContentsObserver { | 143 : public content::WebContentsObserver { |
157 public: | 144 public: |
158 UIThreadResponseCallbackWrapper( | 145 UIThreadResponseCallbackWrapper( |
159 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, | 146 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, |
160 content::RenderFrameHost* render_frame_host) | 147 content::RenderFrameHost* render_frame_host) |
(...skipping 27 matching lines...) Expand all Loading... |
188 weak_ptr_factory_.GetWeakPtr(), | 175 weak_ptr_factory_.GetWeakPtr(), |
189 request_id); | 176 request_id); |
190 } | 177 } |
191 | 178 |
192 private: | 179 private: |
193 void OnExtensionFunctionCompleted(int request_id, | 180 void OnExtensionFunctionCompleted(int request_id, |
194 ExtensionFunction::ResponseType type, | 181 ExtensionFunction::ResponseType type, |
195 const base::ListValue& results, | 182 const base::ListValue& results, |
196 const std::string& error, | 183 const std::string& error, |
197 functions::HistogramValue histogram_value) { | 184 functions::HistogramValue histogram_value) { |
198 base::Process process = | |
199 content::RenderProcessHost::run_renderer_in_process() | |
200 ? base::Process::Current() | |
201 : base::Process::DeprecatedGetProcessFromHandle( | |
202 render_frame_host_->GetProcess()->GetHandle()); | |
203 CommonResponseCallback(render_frame_host_, | 185 CommonResponseCallback(render_frame_host_, |
204 render_frame_host_->GetRoutingID(), | 186 render_frame_host_->GetRoutingID(), |
205 process, request_id, type, results, error, | 187 render_frame_host_->GetProcess(), request_id, type, |
206 histogram_value); | 188 results, error, histogram_value); |
207 } | 189 } |
208 | 190 |
209 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 191 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
210 content::RenderFrameHost* render_frame_host_; | 192 content::RenderFrameHost* render_frame_host_; |
211 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; | 193 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; |
212 | 194 |
213 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); | 195 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); |
214 }; | 196 }; |
215 | 197 |
216 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper | 198 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 } | 241 } |
260 | 242 |
261 void OnExtensionFunctionCompleted(int request_id, | 243 void OnExtensionFunctionCompleted(int request_id, |
262 ExtensionFunction::ResponseType type, | 244 ExtensionFunction::ResponseType type, |
263 const base::ListValue& results, | 245 const base::ListValue& results, |
264 const std::string& error, | 246 const std::string& error, |
265 functions::HistogramValue histogram_value) { | 247 functions::HistogramValue histogram_value) { |
266 content::RenderProcessHost* sender = | 248 content::RenderProcessHost* sender = |
267 content::RenderProcessHost::FromID(render_process_id_); | 249 content::RenderProcessHost::FromID(render_process_id_); |
268 if (type == ExtensionFunction::BAD_MESSAGE) { | 250 if (type == ExtensionFunction::BAD_MESSAGE) { |
269 KillBadMessageSenderRPH(sender, histogram_value); | 251 ReceivedBadMessage(sender, bad_message::EFD_BAD_MESSAGE_WORKER, |
| 252 histogram_value); |
270 return; | 253 return; |
271 } | 254 } |
272 DCHECK(sender); | 255 DCHECK(sender); |
273 sender->Send(new ExtensionMsg_ResponseWorker( | 256 sender->Send(new ExtensionMsg_ResponseWorker( |
274 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, | 257 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, |
275 results, error)); | 258 results, error)); |
276 } | 259 } |
277 | 260 |
278 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 261 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
279 ScopedObserver<content::RenderProcessHost, | 262 ScopedObserver<content::RenderProcessHost, |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
650 // static | 633 // static |
651 void ExtensionFunctionDispatcher::SendAccessDenied( | 634 void ExtensionFunctionDispatcher::SendAccessDenied( |
652 const ExtensionFunction::ResponseCallback& callback, | 635 const ExtensionFunction::ResponseCallback& callback, |
653 functions::HistogramValue histogram_value) { | 636 functions::HistogramValue histogram_value) { |
654 base::ListValue empty_list; | 637 base::ListValue empty_list; |
655 callback.Run(ExtensionFunction::FAILED, empty_list, | 638 callback.Run(ExtensionFunction::FAILED, empty_list, |
656 "Access to extension API denied.", histogram_value); | 639 "Access to extension API denied.", histogram_value); |
657 } | 640 } |
658 | 641 |
659 } // namespace extensions | 642 } // namespace extensions |
OLD | NEW |