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. | |
| 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 on the renderer. | |
|
Devlin
2017/01/13 02:45:50
s/on the renderer/. We flag something as a bad me
lazyboy
2017/01/13 03:04:53
Done.
| |
| 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 using BadMessageReceivedFunc = base::Callback<void(functions::HistogramValue)>; |
| 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 | 92 |
| 116 void CommonResponseCallback(IPC::Sender* ipc_sender, | 93 void CommonResponseCallback(IPC::Sender* ipc_sender, |
|
Devlin
2017/01/13 02:45:50
instead of BadMessageReceivedFunc, could we just h
lazyboy
2017/01/13 03:04:53
Ty, Done.
| |
| 117 int routing_id, | 94 int routing_id, |
| 118 const base::Process& peer_process, | 95 const BadMessageReceivedFunc& bad_message_func, |
| 119 int request_id, | 96 int request_id, |
| 120 ExtensionFunction::ResponseType type, | 97 ExtensionFunction::ResponseType type, |
| 121 const base::ListValue& results, | 98 const base::ListValue& results, |
| 122 const std::string& error, | 99 const std::string& error, |
| 123 functions::HistogramValue histogram_value) { | 100 functions::HistogramValue histogram_value) { |
| 124 DCHECK(ipc_sender); | 101 DCHECK(ipc_sender); |
| 125 | 102 |
| 126 if (type == ExtensionFunction::BAD_MESSAGE) { | 103 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 127 KillBadMessageSender(peer_process, histogram_value); | 104 bad_message_func.Run(histogram_value); |
| 128 return; | 105 return; |
| 129 } | 106 } |
| 130 | 107 |
| 131 ipc_sender->Send(new ExtensionMsg_Response( | 108 ipc_sender->Send(new ExtensionMsg_Response( |
| 132 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, | 109 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, |
| 133 error)); | 110 error)); |
| 134 } | 111 } |
| 135 | 112 |
| 113 void SendBadMessageToFilter(content::BrowserMessageFilter* filter, | |
| 114 functions::HistogramValue histogram_value) { | |
| 115 LogBadMessage(histogram_value); | |
| 116 bad_message::ReceivedBadMessage(filter, bad_message::EFD_BAD_MESSAGE); | |
| 117 } | |
| 118 | |
| 119 void SendBadMessageToProcess(content::RenderProcessHost* rph, | |
| 120 functions::HistogramValue histogram_value) { | |
| 121 LogBadMessage(histogram_value); | |
| 122 bad_message::ReceivedBadMessage(rph, bad_message::EFD_BAD_MESSAGE); | |
| 123 } | |
| 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 // Extract the pointer |filter_ptr| to make the base::Bind call below happy. |
| 148 base::Process::DeprecatedGetProcessFromHandle(ipc_sender->PeerHandle()); | 137 IOThreadExtensionMessageFilter* filter_ptr = ipc_sender.get(); |
| 149 CommonResponseCallback(ipc_sender.get(), routing_id, peer_process, request_id, | 138 BadMessageReceivedFunc bad_message_received_func = |
| 150 type, results, error, histogram_value); | 139 base::Bind(&SendBadMessageToFilter, filter_ptr); |
| 140 CommonResponseCallback(ipc_sender.get(), routing_id, | |
| 141 bad_message_received_func, request_id, type, results, | |
| 142 error, histogram_value); | |
| 151 } | 143 } |
| 152 | 144 |
| 153 } // namespace | 145 } // namespace |
| 154 | 146 |
| 155 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper | 147 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper |
| 156 : public content::WebContentsObserver { | 148 : public content::WebContentsObserver { |
| 157 public: | 149 public: |
| 158 UIThreadResponseCallbackWrapper( | 150 UIThreadResponseCallbackWrapper( |
| 159 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, | 151 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, |
| 160 content::RenderFrameHost* render_frame_host) | 152 content::RenderFrameHost* render_frame_host) |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 188 weak_ptr_factory_.GetWeakPtr(), | 180 weak_ptr_factory_.GetWeakPtr(), |
| 189 request_id); | 181 request_id); |
| 190 } | 182 } |
| 191 | 183 |
| 192 private: | 184 private: |
| 193 void OnExtensionFunctionCompleted(int request_id, | 185 void OnExtensionFunctionCompleted(int request_id, |
| 194 ExtensionFunction::ResponseType type, | 186 ExtensionFunction::ResponseType type, |
| 195 const base::ListValue& results, | 187 const base::ListValue& results, |
| 196 const std::string& error, | 188 const std::string& error, |
| 197 functions::HistogramValue histogram_value) { | 189 functions::HistogramValue histogram_value) { |
| 198 base::Process process = | 190 BadMessageReceivedFunc bad_message_received_func = |
| 199 content::RenderProcessHost::run_renderer_in_process() | 191 base::Bind(&SendBadMessageToProcess, render_frame_host_->GetProcess()); |
| 200 ? base::Process::Current() | |
| 201 : base::Process::DeprecatedGetProcessFromHandle( | |
| 202 render_frame_host_->GetProcess()->GetHandle()); | |
| 203 CommonResponseCallback(render_frame_host_, | 192 CommonResponseCallback(render_frame_host_, |
| 204 render_frame_host_->GetRoutingID(), | 193 render_frame_host_->GetRoutingID(), |
| 205 process, request_id, type, results, error, | 194 bad_message_received_func, request_id, type, results, |
| 206 histogram_value); | 195 error, histogram_value); |
| 207 } | 196 } |
| 208 | 197 |
| 209 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 198 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 210 content::RenderFrameHost* render_frame_host_; | 199 content::RenderFrameHost* render_frame_host_; |
| 211 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; | 200 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; |
| 212 | 201 |
| 213 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); | 202 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); |
| 214 }; | 203 }; |
| 215 | 204 |
| 216 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper | 205 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 } | 248 } |
| 260 | 249 |
| 261 void OnExtensionFunctionCompleted(int request_id, | 250 void OnExtensionFunctionCompleted(int request_id, |
| 262 ExtensionFunction::ResponseType type, | 251 ExtensionFunction::ResponseType type, |
| 263 const base::ListValue& results, | 252 const base::ListValue& results, |
| 264 const std::string& error, | 253 const std::string& error, |
| 265 functions::HistogramValue histogram_value) { | 254 functions::HistogramValue histogram_value) { |
| 266 content::RenderProcessHost* sender = | 255 content::RenderProcessHost* sender = |
| 267 content::RenderProcessHost::FromID(render_process_id_); | 256 content::RenderProcessHost::FromID(render_process_id_); |
| 268 if (type == ExtensionFunction::BAD_MESSAGE) { | 257 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 269 KillBadMessageSenderRPH(sender, histogram_value); | 258 SendBadMessageToProcess(sender, histogram_value); |
| 270 return; | 259 return; |
| 271 } | 260 } |
| 272 DCHECK(sender); | 261 DCHECK(sender); |
| 273 sender->Send(new ExtensionMsg_ResponseWorker( | 262 sender->Send(new ExtensionMsg_ResponseWorker( |
| 274 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, | 263 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, |
| 275 results, error)); | 264 results, error)); |
| 276 } | 265 } |
| 277 | 266 |
| 278 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 267 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 279 ScopedObserver<content::RenderProcessHost, | 268 ScopedObserver<content::RenderProcessHost, |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 // static | 639 // static |
| 651 void ExtensionFunctionDispatcher::SendAccessDenied( | 640 void ExtensionFunctionDispatcher::SendAccessDenied( |
| 652 const ExtensionFunction::ResponseCallback& callback, | 641 const ExtensionFunction::ResponseCallback& callback, |
| 653 functions::HistogramValue histogram_value) { | 642 functions::HistogramValue histogram_value) { |
| 654 base::ListValue empty_list; | 643 base::ListValue empty_list; |
| 655 callback.Run(ExtensionFunction::FAILED, empty_list, | 644 callback.Run(ExtensionFunction::FAILED, empty_list, |
| 656 "Access to extension API denied.", histogram_value); | 645 "Access to extension API denied.", histogram_value); |
| 657 } | 646 } |
| 658 | 647 |
| 659 } // namespace extensions | 648 } // namespace extensions |
| OLD | NEW |