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 |