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

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

Issue 2629783002: Upload crash reports when ExtensionFunctions generate bad messages. (Closed)
Patch Set: address comments 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.
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
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
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
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
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