1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/public/browser/browser_message_filter.h"
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/debug/dump_without_crashing.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/process/process_handle.h"
14 #include "base/task_runner.h"
15 #include "build/build_config.h"
16 #include "content/browser/browser_child_process_host_impl.h"
17 #include "content/browser/child_process_launcher.h"
18 #include "content/public/browser/browser_task_traits.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/common/result_codes.h"
21 #include "ipc/ipc_sync_message.h"
22 #include "ipc/message_filter.h"
23 
24 using content::BrowserMessageFilter;
25 
26 namespace content {
27 
28 class BrowserMessageFilter::Internal : public IPC::MessageFilter {
29  public:
Internal(BrowserMessageFilter * filter)30   explicit Internal(BrowserMessageFilter* filter) : filter_(filter) {}
31 
32  private:
~Internal()33   ~Internal() override {}
34 
35   // IPC::MessageFilter implementation:
OnFilterAdded(IPC::Channel * channel)36   void OnFilterAdded(IPC::Channel* channel) override {
37     filter_->sender_ = channel;
38     filter_->OnFilterAdded(channel);
39   }
40 
OnFilterRemoved()41   void OnFilterRemoved() override {
42     for (auto& callback : filter_->filter_removed_callbacks_)
43       std::move(callback).Run();
44     filter_->filter_removed_callbacks_.clear();
45     filter_->OnFilterRemoved();
46   }
47 
OnChannelClosing()48   void OnChannelClosing() override {
49     filter_->sender_ = nullptr;
50     filter_->OnChannelClosing();
51   }
52 
OnChannelError()53   void OnChannelError() override { filter_->OnChannelError(); }
54 
OnChannelConnected(int32_t peer_pid)55   void OnChannelConnected(int32_t peer_pid) override {
56     filter_->peer_process_ = base::Process::OpenWithExtraPrivileges(peer_pid);
57     filter_->OnChannelConnected(peer_pid);
58   }
59 
OnMessageReceived(const IPC::Message & message)60   bool OnMessageReceived(const IPC::Message& message) override {
61     DCHECK_CURRENTLY_ON(BrowserThread::IO);
62 
63     BrowserThread::ID thread = BrowserThread::IO;
64     filter_->OverrideThreadForMessage(message, &thread);
65 
66     scoped_refptr<base::SequencedTaskRunner> destination;
67     if (thread == BrowserThread::UI) {
68       destination = GetUIThreadTaskRunner({});
69     } else {
70       DCHECK_EQ(thread, BrowserThread::IO);
71 
72       destination = filter_->OverrideTaskRunnerForMessage(message);
73 
74       // Neither override kicked in, dispatch the message immediately from the
75       // IO thread.
76       if (!destination)
77         return DispatchMessage(message);
78     }
79 
80     DCHECK(destination);
81     destination->PostTask(
82         FROM_HERE,
83         base::BindOnce(base::IgnoreResult(&Internal::DispatchMessage), this,
84                        message));
85     return true;
86   }
87 
GetSupportedMessageClasses(std::vector<uint32_t> * supported_message_classes) const88   bool GetSupportedMessageClasses(
89       std::vector<uint32_t>* supported_message_classes) const override {
90     supported_message_classes->assign(
91         filter_->message_classes_to_filter().begin(),
92         filter_->message_classes_to_filter().end());
93     return true;
94   }
95 
96   // Dispatches a message to the derived class.
DispatchMessage(const IPC::Message & message)97   bool DispatchMessage(const IPC::Message& message) {
98     bool rv = filter_->OnMessageReceived(message);
99     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) || rv) <<
100         "Must handle messages that were dispatched to another thread!";
101     return rv;
102   }
103 
104   scoped_refptr<BrowserMessageFilter> filter_;
105 
106   DISALLOW_COPY_AND_ASSIGN(Internal);
107 };
108 
BrowserMessageFilter(uint32_t message_class_to_filter)109 BrowserMessageFilter::BrowserMessageFilter(uint32_t message_class_to_filter)
110     : internal_(nullptr),
111       sender_(nullptr),
112       message_classes_to_filter_(1, message_class_to_filter) {}
113 
BrowserMessageFilter(const uint32_t * message_classes_to_filter,size_t num_message_classes_to_filter)114 BrowserMessageFilter::BrowserMessageFilter(
115     const uint32_t* message_classes_to_filter,
116     size_t num_message_classes_to_filter)
117     : internal_(nullptr),
118       sender_(nullptr),
119       message_classes_to_filter_(
120           message_classes_to_filter,
121           message_classes_to_filter + num_message_classes_to_filter) {
122   DCHECK(num_message_classes_to_filter);
123 }
124 
AddAssociatedInterface(const std::string & name,const IPC::ChannelProxy::GenericAssociatedInterfaceFactory & factory,base::OnceClosure filter_removed_callback)125 void BrowserMessageFilter::AddAssociatedInterface(
126     const std::string& name,
127     const IPC::ChannelProxy::GenericAssociatedInterfaceFactory& factory,
128     base::OnceClosure filter_removed_callback) {
129   associated_interfaces_.emplace_back(name, factory);
130   filter_removed_callbacks_.emplace_back(std::move(filter_removed_callback));
131 }
132 
PeerHandle()133 base::ProcessHandle BrowserMessageFilter::PeerHandle() {
134   return peer_process_.Handle();
135 }
136 
OnDestruct() const137 void BrowserMessageFilter::OnDestruct() const {
138   delete this;
139 }
140 
Send(IPC::Message * message)141 bool BrowserMessageFilter::Send(IPC::Message* message) {
142   if (message->is_sync()) {
143     // We don't support sending synchronous messages from the browser.  If we
144     // really needed it, we can make this class derive from SyncMessageFilter
145     // but it seems better to not allow sending synchronous messages from the
146     // browser, since it might allow a corrupt/malicious renderer to hang us.
147     NOTREACHED() << "Can't send sync message through BrowserMessageFilter!";
148     return false;
149   }
150 
151   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
152     GetIOThreadTaskRunner({})->PostTask(
153         FROM_HERE,
154         base::BindOnce(base::IgnoreResult(&BrowserMessageFilter::Send), this,
155                        message));
156     return true;
157   }
158 
159   if (sender_)
160     return sender_->Send(message);
161 
162   delete message;
163   return false;
164 }
165 
166 scoped_refptr<base::SequencedTaskRunner>
OverrideTaskRunnerForMessage(const IPC::Message & message)167 BrowserMessageFilter::OverrideTaskRunnerForMessage(
168     const IPC::Message& message) {
169   return nullptr;
170 }
171 
ShutdownForBadMessage()172 void BrowserMessageFilter::ShutdownForBadMessage() {
173   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
174   if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
175     return;
176 
177   if (base::Process::Current().Handle() == peer_process_.Handle()) {
178     // Just crash in single process. Matches RenderProcessHostImpl behavior.
179     CHECK(false);
180   }
181 
182   ChildProcessLauncher::TerminateProcess(
183       peer_process_, content::RESULT_CODE_KILLED_BAD_MESSAGE);
184 
185   // Report a crash, since none will be generated by the killed renderer.
186   base::debug::DumpWithoutCrashing();
187 
188   // Log the renderer kill to the histogram tracking all kills.
189   BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
190       PROCESS_TYPE_RENDERER);
191 }
192 
~BrowserMessageFilter()193 BrowserMessageFilter::~BrowserMessageFilter() {
194 }
195 
GetFilter()196 IPC::MessageFilter* BrowserMessageFilter::GetFilter() {
197   // We create this on demand so that if a filter is used in a unit test but
198   // never attached to a channel, we don't leak Internal and this;
199   DCHECK(!internal_) << "Should only be called once.";
200   internal_ = new Internal(this);
201   return internal_;
202 }
203 
RegisterAssociatedInterfaces(IPC::ChannelProxy * proxy)204 void BrowserMessageFilter::RegisterAssociatedInterfaces(
205     IPC::ChannelProxy* proxy) {
206   for (const auto& entry : associated_interfaces_)
207     proxy->AddGenericAssociatedInterfaceForIOThread(entry.first, entry.second);
208   associated_interfaces_.clear();
209 }
210 
211 }  // namespace content
212