Chromium Code Reviews| 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 // in that API's implementation on the renderer. | |
| 85 void KillBadMessageSender(const base::Process& process, | |
| 86 functions::HistogramValue histogram_value) { | |
| 87 // The renderer has done validation before sending extension api requests. | |
| 88 // 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 | |
| 90 // attacker trying to exploit the browser, so we crash the renderer instead. | |
|
Charlie Reis
2017/01/13 21:22:25
Is there somewhere you can preserve this comment?
lazyboy
2017/01/14 01:04:43
Restored the comment.
| |
| 91 LOG(ERROR) << "Terminating renderer because of malformed extension message."; | |
| 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")); | 84 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); |
| 85 // Track the specific function's |histogram_value|, as this may indicate a | |
| 86 // bug in that API's implementation. | |
| 100 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", | 87 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", |
| 101 histogram_value, functions::ENUM_BOUNDARY); | 88 histogram_value, functions::ENUM_BOUNDARY); |
| 102 if (process.IsValid()) | |
| 103 process.Terminate(content::RESULT_CODE_KILLED_BAD_MESSAGE, false); | |
| 104 } | 89 } |
| 105 | 90 |
| 106 void KillBadMessageSenderRPH(content::RenderProcessHost* sender_process_host, | 91 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, | 92 void CommonResponseCallback(IPC::Sender* ipc_sender, |
| 117 int routing_id, | 93 int routing_id, |
| 118 const base::Process& peer_process, | 94 T bad_message_sender, |
|
Devlin
2017/01/13 16:16:17
nitty nit: Let's use T* (so that T is RenderProces
lazyboy
2017/01/14 01:04:43
Done.
| |
| 119 int request_id, | 95 int request_id, |
| 120 ExtensionFunction::ResponseType type, | 96 ExtensionFunction::ResponseType type, |
| 121 const base::ListValue& results, | 97 const base::ListValue& results, |
| 122 const std::string& error, | 98 const std::string& error, |
| 123 functions::HistogramValue histogram_value) { | 99 functions::HistogramValue histogram_value) { |
| 124 DCHECK(ipc_sender); | 100 DCHECK(ipc_sender); |
| 125 | 101 |
| 126 if (type == ExtensionFunction::BAD_MESSAGE) { | 102 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 127 KillBadMessageSender(peer_process, histogram_value); | 103 LogBadMessage(histogram_value); |
| 104 bad_message::ReceivedBadMessage(bad_message_sender, | |
| 105 bad_message::EFD_BAD_MESSAGE); | |
| 128 return; | 106 return; |
| 129 } | 107 } |
| 130 | 108 |
| 131 ipc_sender->Send(new ExtensionMsg_Response( | 109 ipc_sender->Send(new ExtensionMsg_Response( |
| 132 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, | 110 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, |
| 133 error)); | 111 error)); |
| 134 } | 112 } |
| 135 | 113 |
| 136 void IOThreadResponseCallback( | 114 void IOThreadResponseCallback( |
| 137 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, | 115 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, |
| 138 int routing_id, | 116 int routing_id, |
| 139 int request_id, | 117 int request_id, |
| 140 ExtensionFunction::ResponseType type, | 118 ExtensionFunction::ResponseType type, |
| 141 const base::ListValue& results, | 119 const base::ListValue& results, |
| 142 const std::string& error, | 120 const std::string& error, |
| 143 functions::HistogramValue histogram_value) { | 121 functions::HistogramValue histogram_value) { |
| 144 if (!ipc_sender.get()) | 122 if (!ipc_sender.get()) |
| 145 return; | 123 return; |
| 146 | 124 |
| 147 base::Process peer_process = | 125 CommonResponseCallback(ipc_sender.get(), routing_id, ipc_sender.get(), |
| 148 base::Process::DeprecatedGetProcessFromHandle(ipc_sender->PeerHandle()); | 126 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 } | 127 } |
| 152 | 128 |
| 153 } // namespace | 129 } // namespace |
| 154 | 130 |
| 155 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper | 131 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper |
| 156 : public content::WebContentsObserver { | 132 : public content::WebContentsObserver { |
| 157 public: | 133 public: |
| 158 UIThreadResponseCallbackWrapper( | 134 UIThreadResponseCallbackWrapper( |
| 159 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, | 135 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, |
| 160 content::RenderFrameHost* render_frame_host) | 136 content::RenderFrameHost* render_frame_host) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 188 weak_ptr_factory_.GetWeakPtr(), | 164 weak_ptr_factory_.GetWeakPtr(), |
| 189 request_id); | 165 request_id); |
| 190 } | 166 } |
| 191 | 167 |
| 192 private: | 168 private: |
| 193 void OnExtensionFunctionCompleted(int request_id, | 169 void OnExtensionFunctionCompleted(int request_id, |
| 194 ExtensionFunction::ResponseType type, | 170 ExtensionFunction::ResponseType type, |
| 195 const base::ListValue& results, | 171 const base::ListValue& results, |
| 196 const std::string& error, | 172 const std::string& error, |
| 197 functions::HistogramValue histogram_value) { | 173 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_, | 174 CommonResponseCallback(render_frame_host_, |
| 204 render_frame_host_->GetRoutingID(), | 175 render_frame_host_->GetRoutingID(), |
| 205 process, request_id, type, results, error, | 176 render_frame_host_->GetProcess(), request_id, type, |
| 206 histogram_value); | 177 results, error, histogram_value); |
| 207 } | 178 } |
| 208 | 179 |
| 209 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 180 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 210 content::RenderFrameHost* render_frame_host_; | 181 content::RenderFrameHost* render_frame_host_; |
| 211 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; | 182 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; |
| 212 | 183 |
| 213 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); | 184 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); |
| 214 }; | 185 }; |
| 215 | 186 |
| 216 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper | 187 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 } | 230 } |
| 260 | 231 |
| 261 void OnExtensionFunctionCompleted(int request_id, | 232 void OnExtensionFunctionCompleted(int request_id, |
| 262 ExtensionFunction::ResponseType type, | 233 ExtensionFunction::ResponseType type, |
| 263 const base::ListValue& results, | 234 const base::ListValue& results, |
| 264 const std::string& error, | 235 const std::string& error, |
| 265 functions::HistogramValue histogram_value) { | 236 functions::HistogramValue histogram_value) { |
| 266 content::RenderProcessHost* sender = | 237 content::RenderProcessHost* sender = |
| 267 content::RenderProcessHost::FromID(render_process_id_); | 238 content::RenderProcessHost::FromID(render_process_id_); |
| 268 if (type == ExtensionFunction::BAD_MESSAGE) { | 239 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 269 KillBadMessageSenderRPH(sender, histogram_value); | 240 LogBadMessage(histogram_value); |
| 241 bad_message::ReceivedBadMessage(sender, bad_message::EFD_BAD_MESSAGE); | |
|
Charlie Reis
2017/01/13 21:22:25
Please use a unique BadMessageReason in each Recei
lazyboy
2017/01/14 01:04:43
Done.
| |
| 270 return; | 242 return; |
| 271 } | 243 } |
| 272 DCHECK(sender); | 244 DCHECK(sender); |
| 273 sender->Send(new ExtensionMsg_ResponseWorker( | 245 sender->Send(new ExtensionMsg_ResponseWorker( |
| 274 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, | 246 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, |
| 275 results, error)); | 247 results, error)); |
| 276 } | 248 } |
| 277 | 249 |
| 278 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 250 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 279 ScopedObserver<content::RenderProcessHost, | 251 ScopedObserver<content::RenderProcessHost, |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 // static | 622 // static |
| 651 void ExtensionFunctionDispatcher::SendAccessDenied( | 623 void ExtensionFunctionDispatcher::SendAccessDenied( |
| 652 const ExtensionFunction::ResponseCallback& callback, | 624 const ExtensionFunction::ResponseCallback& callback, |
| 653 functions::HistogramValue histogram_value) { | 625 functions::HistogramValue histogram_value) { |
| 654 base::ListValue empty_list; | 626 base::ListValue empty_list; |
| 655 callback.Run(ExtensionFunction::FAILED, empty_list, | 627 callback.Run(ExtensionFunction::FAILED, empty_list, |
| 656 "Access to extension API denied.", histogram_value); | 628 "Access to extension API denied.", histogram_value); |
| 657 } | 629 } |
| 658 | 630 |
| 659 } // namespace extensions | 631 } // namespace extensions |
| OLD | NEW |