Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: extensions/browser/extension_function_dispatcher.cc

Issue 2629783002: Upload crash reports when ExtensionFunctions generate bad messages. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« extensions/browser/bad_message.cc ('K') | « extensions/browser/bad_message.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698