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

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

Issue 957113002: [Extensions] Record the extension function names which send a bad message. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: format somebody else's histogram... Created 5 years, 9 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_string_value_serializer.h" 8 #include "base/json/json_string_value_serializer.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/metrics/histogram_macros.h"
12 #include "base/metrics/sparse_histogram.h" 13 #include "base/metrics/sparse_histogram.h"
13 #include "base/process/process.h" 14 #include "base/process/process.h"
14 #include "base/profiler/scoped_profile.h" 15 #include "base/profiler/scoped_profile.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 #include "build/build_config.h" 17 #include "build/build_config.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/render_frame_host.h" 19 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h" 20 #include "content/public/browser/render_process_host.h"
20 #include "content/public/browser/render_view_host.h" 21 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/user_metrics.h" 22 #include "content/public/browser/user_metrics.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 // Separate copy of ExtensionAPI used for IO thread extension functions. We need 75 // Separate copy of ExtensionAPI used for IO thread extension functions. We need
75 // this because ExtensionAPI has mutable data. It should be possible to remove 76 // this because ExtensionAPI has mutable data. It should be possible to remove
76 // this once all the extension APIs are updated to the feature system. 77 // this once all the extension APIs are updated to the feature system.
77 struct Static { 78 struct Static {
78 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} 79 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {}
79 scoped_ptr<ExtensionAPI> api; 80 scoped_ptr<ExtensionAPI> api;
80 }; 81 };
81 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; 82 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
82 83
83 // Kills the specified process because it sends us a malformed message. 84 // Kills the specified process because it sends us a malformed message.
84 void KillBadMessageSender(base::ProcessHandle process) { 85 // Track the specific function's |histogram_value|, as this may indicate a bug
86 // in that API's implementation on the renderer.
87 void KillBadMessageSender(base::ProcessHandle process,
88 functions::HistogramValue histogram_value) {
85 NOTREACHED(); 89 NOTREACHED();
86 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); 90 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD"));
91 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName",
92 histogram_value, functions::ENUM_BOUNDARY);
87 if (process) 93 if (process)
88 base::KillProcess(process, content::RESULT_CODE_KILLED_BAD_MESSAGE, false); 94 base::KillProcess(process, content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
89 } 95 }
90 96
91 void CommonResponseCallback(IPC::Sender* ipc_sender, 97 void CommonResponseCallback(IPC::Sender* ipc_sender,
92 int routing_id, 98 int routing_id,
93 base::ProcessHandle peer_process, 99 base::ProcessHandle peer_process,
94 int request_id, 100 int request_id,
95 ExtensionFunction::ResponseType type, 101 ExtensionFunction::ResponseType type,
96 const base::ListValue& results, 102 const base::ListValue& results,
97 const std::string& error) { 103 const std::string& error,
104 functions::HistogramValue histogram_value) {
98 DCHECK(ipc_sender); 105 DCHECK(ipc_sender);
99 106
100 if (type == ExtensionFunction::BAD_MESSAGE) { 107 if (type == ExtensionFunction::BAD_MESSAGE) {
101 // The renderer has done validation before sending extension api requests. 108 // The renderer has done validation before sending extension api requests.
102 // Therefore, we should never receive a request that is invalid in a way 109 // Therefore, we should never receive a request that is invalid in a way
103 // that JSON validation in the renderer should have caught. It could be an 110 // that JSON validation in the renderer should have caught. It could be an
104 // attacker trying to exploit the browser, so we crash the renderer instead. 111 // attacker trying to exploit the browser, so we crash the renderer instead.
105 LOG(ERROR) << 112 LOG(ERROR) <<
106 "Terminating renderer because of malformed extension message."; 113 "Terminating renderer because of malformed extension message.";
107 if (content::RenderProcessHost::run_renderer_in_process()) { 114 if (content::RenderProcessHost::run_renderer_in_process()) {
108 // In single process mode it is better if we don't suicide but just crash. 115 // In single process mode it is better if we don't suicide but just crash.
109 CHECK(false); 116 CHECK(false);
110 } else { 117 } else {
111 KillBadMessageSender(peer_process); 118 KillBadMessageSender(peer_process, histogram_value);
112 } 119 }
113
114 return; 120 return;
115 } 121 }
116 122
117 ipc_sender->Send(new ExtensionMsg_Response( 123 ipc_sender->Send(new ExtensionMsg_Response(
118 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, 124 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results,
119 error)); 125 error));
120 } 126 }
121 127
122 void IOThreadResponseCallback( 128 void IOThreadResponseCallback(
123 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, 129 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender,
124 int routing_id, 130 int routing_id,
125 int request_id, 131 int request_id,
126 ExtensionFunction::ResponseType type, 132 ExtensionFunction::ResponseType type,
127 const base::ListValue& results, 133 const base::ListValue& results,
128 const std::string& error) { 134 const std::string& error,
135 functions::HistogramValue histogram_value) {
129 if (!ipc_sender.get()) 136 if (!ipc_sender.get())
130 return; 137 return;
131 138
132 CommonResponseCallback(ipc_sender.get(), 139 CommonResponseCallback(ipc_sender.get(), routing_id, ipc_sender->PeerHandle(),
133 routing_id, 140 request_id, type, results, error, histogram_value);
134 ipc_sender->PeerHandle(),
135 request_id,
136 type,
137 results,
138 error);
139 } 141 }
140 142
141 } // namespace 143 } // namespace
142 144
143 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper 145 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper
144 : public content::WebContentsObserver { 146 : public content::WebContentsObserver {
145 public: 147 public:
146 UIThreadResponseCallbackWrapper( 148 UIThreadResponseCallbackWrapper(
147 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, 149 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher,
148 RenderViewHost* render_view_host) 150 RenderViewHost* render_view_host)
(...skipping 24 matching lines...) Expand all
173 return base::Bind( 175 return base::Bind(
174 &UIThreadResponseCallbackWrapper::OnExtensionFunctionCompleted, 176 &UIThreadResponseCallbackWrapper::OnExtensionFunctionCompleted,
175 weak_ptr_factory_.GetWeakPtr(), 177 weak_ptr_factory_.GetWeakPtr(),
176 request_id); 178 request_id);
177 } 179 }
178 180
179 private: 181 private:
180 void OnExtensionFunctionCompleted(int request_id, 182 void OnExtensionFunctionCompleted(int request_id,
181 ExtensionFunction::ResponseType type, 183 ExtensionFunction::ResponseType type,
182 const base::ListValue& results, 184 const base::ListValue& results,
183 const std::string& error) { 185 const std::string& error,
184 CommonResponseCallback( 186 functions::HistogramValue histogram_value) {
185 render_view_host_, render_view_host_->GetRoutingID(), 187 CommonResponseCallback(render_view_host_, render_view_host_->GetRoutingID(),
186 render_view_host_->GetProcess()->GetHandle(), request_id, type, 188 render_view_host_->GetProcess()->GetHandle(),
187 results, error); 189 request_id, type, results, error, histogram_value);
188 } 190 }
189 191
190 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; 192 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
191 content::RenderViewHost* render_view_host_; 193 content::RenderViewHost* render_view_host_;
192 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; 194 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_;
193 195
194 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); 196 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper);
195 }; 197 };
196 198
197 WindowController* 199 WindowController*
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 } 433 }
432 } 434 }
433 435
434 // static 436 // static
435 bool ExtensionFunctionDispatcher::CheckPermissions( 437 bool ExtensionFunctionDispatcher::CheckPermissions(
436 ExtensionFunction* function, 438 ExtensionFunction* function,
437 const ExtensionHostMsg_Request_Params& params, 439 const ExtensionHostMsg_Request_Params& params,
438 const ExtensionFunction::ResponseCallback& callback) { 440 const ExtensionFunction::ResponseCallback& callback) {
439 if (!function->HasPermission()) { 441 if (!function->HasPermission()) {
440 LOG(ERROR) << "Permission denied for " << params.name; 442 LOG(ERROR) << "Permission denied for " << params.name;
441 SendAccessDenied(callback); 443 SendAccessDenied(callback, function->histogram_value());
442 return false; 444 return false;
443 } 445 }
444 return true; 446 return true;
445 } 447 }
446 448
447 // static 449 // static
448 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction( 450 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
449 const ExtensionHostMsg_Request_Params& params, 451 const ExtensionHostMsg_Request_Params& params,
450 const Extension* extension, 452 const Extension* extension,
451 int requesting_process_id, 453 int requesting_process_id,
452 const ProcessMap& process_map, 454 const ProcessMap& process_map,
453 ExtensionAPI* api, 455 ExtensionAPI* api,
454 void* profile_id, 456 void* profile_id,
455 const ExtensionFunction::ResponseCallback& callback) { 457 const ExtensionFunction::ResponseCallback& callback) {
456 ExtensionFunction* function = 458 ExtensionFunction* function =
457 ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name); 459 ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name);
458 if (!function) { 460 if (!function) {
459 LOG(ERROR) << "Unknown Extension API - " << params.name; 461 LOG(ERROR) << "Unknown Extension API - " << params.name;
460 SendAccessDenied(callback); 462 SendAccessDenied(callback, function->histogram_value());
461 return NULL; 463 return NULL;
462 } 464 }
463 465
464 function->SetArgs(&params.arguments); 466 function->SetArgs(&params.arguments);
465 function->set_source_url(params.source_url); 467 function->set_source_url(params.source_url);
466 function->set_request_id(params.request_id); 468 function->set_request_id(params.request_id);
467 function->set_has_callback(params.has_callback); 469 function->set_has_callback(params.has_callback);
468 function->set_user_gesture(params.user_gesture); 470 function->set_user_gesture(params.user_gesture);
469 function->set_extension(extension); 471 function->set_extension(extension);
470 function->set_profile_id(profile_id); 472 function->set_profile_id(profile_id);
471 function->set_response_callback(callback); 473 function->set_response_callback(callback);
472 function->set_source_tab_id(params.source_tab_id); 474 function->set_source_tab_id(params.source_tab_id);
473 function->set_source_context_type( 475 function->set_source_context_type(
474 process_map.GetMostLikelyContextType(extension, requesting_process_id)); 476 process_map.GetMostLikelyContextType(extension, requesting_process_id));
475 477
476 return function; 478 return function;
477 } 479 }
478 480
479 // static 481 // static
480 void ExtensionFunctionDispatcher::SendAccessDenied( 482 void ExtensionFunctionDispatcher::SendAccessDenied(
481 const ExtensionFunction::ResponseCallback& callback) { 483 const ExtensionFunction::ResponseCallback& callback,
484 functions::HistogramValue histogram_value) {
482 base::ListValue empty_list; 485 base::ListValue empty_list;
483 callback.Run(ExtensionFunction::FAILED, empty_list, 486 callback.Run(ExtensionFunction::FAILED, empty_list,
484 "Access to extension API denied."); 487 "Access to extension API denied.", histogram_value);
485 } 488 }
486 489
487 } // namespace extensions 490 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/browser/extension_function_dispatcher.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698