1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_channel_nacl.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <errno.h>
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker #include <sys/types.h>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include <algorithm>
13*6777b538SAndroid Build Coastguard Worker #include <memory>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_for_io.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/trace_event.h"
24*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_listener.h"
25*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_logging.h"
26*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_message_attachment_set.h"
27*6777b538SAndroid Build Coastguard Worker #include "ipc/ipc_platform_file_attachment_posix.h"
28*6777b538SAndroid Build Coastguard Worker #include "native_client/src/public/imc_syscalls.h"
29*6777b538SAndroid Build Coastguard Worker #include "native_client/src/public/imc_types.h"
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker namespace IPC {
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker struct MessageContents {
34*6777b538SAndroid Build Coastguard Worker std::vector<char> data;
35*6777b538SAndroid Build Coastguard Worker std::vector<int> fds;
36*6777b538SAndroid Build Coastguard Worker };
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker namespace {
39*6777b538SAndroid Build Coastguard Worker
ReadDataOnReaderThread(int pipe,MessageContents * contents)40*6777b538SAndroid Build Coastguard Worker bool ReadDataOnReaderThread(int pipe, MessageContents* contents) {
41*6777b538SAndroid Build Coastguard Worker DCHECK(pipe >= 0);
42*6777b538SAndroid Build Coastguard Worker if (pipe < 0)
43*6777b538SAndroid Build Coastguard Worker return false;
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker contents->data.resize(Channel::kReadBufferSize);
46*6777b538SAndroid Build Coastguard Worker contents->fds.resize(NACL_ABI_IMC_DESC_MAX);
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() };
49*6777b538SAndroid Build Coastguard Worker NaClAbiNaClImcMsgHdr msg = {
50*6777b538SAndroid Build Coastguard Worker &iov, 1, &contents->fds[0], contents->fds.size()
51*6777b538SAndroid Build Coastguard Worker };
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker int bytes_read = imc_recvmsg(pipe, &msg, 0);
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker if (bytes_read <= 0) {
56*6777b538SAndroid Build Coastguard Worker // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either
57*6777b538SAndroid Build Coastguard Worker // due to error or for regular shutdown).
58*6777b538SAndroid Build Coastguard Worker contents->data.clear();
59*6777b538SAndroid Build Coastguard Worker contents->fds.clear();
60*6777b538SAndroid Build Coastguard Worker return false;
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker DCHECK(bytes_read);
63*6777b538SAndroid Build Coastguard Worker // Resize the buffers down to the number of bytes and fds we actually read.
64*6777b538SAndroid Build Coastguard Worker contents->data.resize(bytes_read);
65*6777b538SAndroid Build Coastguard Worker contents->fds.resize(msg.desc_length);
66*6777b538SAndroid Build Coastguard Worker return true;
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker } // namespace
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker // static
72*6777b538SAndroid Build Coastguard Worker constexpr size_t Channel::kMaximumMessageSize;
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker class ChannelNacl::ReaderThreadRunner
75*6777b538SAndroid Build Coastguard Worker : public base::DelegateSimpleThread::Delegate {
76*6777b538SAndroid Build Coastguard Worker public:
77*6777b538SAndroid Build Coastguard Worker // |pipe|: A file descriptor from which we will read using imc_recvmsg.
78*6777b538SAndroid Build Coastguard Worker // |data_read_callback|: A callback we invoke (on the main thread) when we
79*6777b538SAndroid Build Coastguard Worker // have read data.
80*6777b538SAndroid Build Coastguard Worker // |failure_callback|: A callback we invoke when we have a failure reading
81*6777b538SAndroid Build Coastguard Worker // from |pipe|.
82*6777b538SAndroid Build Coastguard Worker // |main_message_loop|: A proxy for the main thread, where we will invoke the
83*6777b538SAndroid Build Coastguard Worker // above callbacks.
84*6777b538SAndroid Build Coastguard Worker ReaderThreadRunner(
85*6777b538SAndroid Build Coastguard Worker int pipe,
86*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(std::unique_ptr<MessageContents>)>
87*6777b538SAndroid Build Coastguard Worker data_read_callback,
88*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void()> failure_callback,
89*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker ReaderThreadRunner(const ReaderThreadRunner&) = delete;
92*6777b538SAndroid Build Coastguard Worker ReaderThreadRunner& operator=(const ReaderThreadRunner&) = delete;
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker // DelegateSimpleThread implementation. Reads data from the pipe in a loop
95*6777b538SAndroid Build Coastguard Worker // until either we are told to quit or a read fails.
96*6777b538SAndroid Build Coastguard Worker void Run() override;
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker private:
99*6777b538SAndroid Build Coastguard Worker int pipe_;
100*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(std::unique_ptr<MessageContents>)>
101*6777b538SAndroid Build Coastguard Worker data_read_callback_;
102*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void()> failure_callback_;
103*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
104*6777b538SAndroid Build Coastguard Worker };
105*6777b538SAndroid Build Coastguard Worker
ReaderThreadRunner(int pipe,base::RepeatingCallback<void (std::unique_ptr<MessageContents>)> data_read_callback,base::RepeatingCallback<void ()> failure_callback,scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)106*6777b538SAndroid Build Coastguard Worker ChannelNacl::ReaderThreadRunner::ReaderThreadRunner(
107*6777b538SAndroid Build Coastguard Worker int pipe,
108*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(std::unique_ptr<MessageContents>)>
109*6777b538SAndroid Build Coastguard Worker data_read_callback,
110*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void()> failure_callback,
111*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
112*6777b538SAndroid Build Coastguard Worker : pipe_(pipe),
113*6777b538SAndroid Build Coastguard Worker data_read_callback_(data_read_callback),
114*6777b538SAndroid Build Coastguard Worker failure_callback_(failure_callback),
115*6777b538SAndroid Build Coastguard Worker main_task_runner_(main_task_runner) {}
116*6777b538SAndroid Build Coastguard Worker
Run()117*6777b538SAndroid Build Coastguard Worker void ChannelNacl::ReaderThreadRunner::Run() {
118*6777b538SAndroid Build Coastguard Worker while (true) {
119*6777b538SAndroid Build Coastguard Worker std::unique_ptr<MessageContents> msg_contents(new MessageContents);
120*6777b538SAndroid Build Coastguard Worker bool success = ReadDataOnReaderThread(pipe_, msg_contents.get());
121*6777b538SAndroid Build Coastguard Worker if (success) {
122*6777b538SAndroid Build Coastguard Worker main_task_runner_->PostTask(
123*6777b538SAndroid Build Coastguard Worker FROM_HERE,
124*6777b538SAndroid Build Coastguard Worker base::BindOnce(data_read_callback_, std::move(msg_contents)));
125*6777b538SAndroid Build Coastguard Worker } else {
126*6777b538SAndroid Build Coastguard Worker main_task_runner_->PostTask(FROM_HERE, failure_callback_);
127*6777b538SAndroid Build Coastguard Worker // Because the read failed, we know we're going to quit. Don't bother
128*6777b538SAndroid Build Coastguard Worker // trying to read again.
129*6777b538SAndroid Build Coastguard Worker return;
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker }
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker
ChannelNacl(const IPC::ChannelHandle & channel_handle,Mode mode,Listener * listener)134*6777b538SAndroid Build Coastguard Worker ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle,
135*6777b538SAndroid Build Coastguard Worker Mode mode,
136*6777b538SAndroid Build Coastguard Worker Listener* listener)
137*6777b538SAndroid Build Coastguard Worker : ChannelReader(listener),
138*6777b538SAndroid Build Coastguard Worker mode_(mode),
139*6777b538SAndroid Build Coastguard Worker waiting_connect_(true),
140*6777b538SAndroid Build Coastguard Worker pipe_(-1),
141*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_(this) {
142*6777b538SAndroid Build Coastguard Worker if (!CreatePipe(channel_handle)) {
143*6777b538SAndroid Build Coastguard Worker // The pipe may have been closed already.
144*6777b538SAndroid Build Coastguard Worker const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
145*6777b538SAndroid Build Coastguard Worker LOG(WARNING) << "Unable to create pipe in " << modestr << " mode";
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
~ChannelNacl()149*6777b538SAndroid Build Coastguard Worker ChannelNacl::~ChannelNacl() {
150*6777b538SAndroid Build Coastguard Worker CleanUp();
151*6777b538SAndroid Build Coastguard Worker Close();
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
Connect()154*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::Connect() {
155*6777b538SAndroid Build Coastguard Worker WillConnect();
156*6777b538SAndroid Build Coastguard Worker
157*6777b538SAndroid Build Coastguard Worker if (pipe_ == -1) {
158*6777b538SAndroid Build Coastguard Worker DLOG(WARNING) << "Channel creation failed";
159*6777b538SAndroid Build Coastguard Worker return false;
160*6777b538SAndroid Build Coastguard Worker }
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker // Note that Connect is called on the "Channel" thread (i.e., the same thread
163*6777b538SAndroid Build Coastguard Worker // where Channel::Send will be called, and the same thread that should receive
164*6777b538SAndroid Build Coastguard Worker // messages). The constructor might be invoked on another thread (see
165*6777b538SAndroid Build Coastguard Worker // ChannelProxy for an example of that). Therefore, we must wait until Connect
166*6777b538SAndroid Build Coastguard Worker // is called to decide which SingleThreadTaskRunner to pass to
167*6777b538SAndroid Build Coastguard Worker // ReaderThreadRunner.
168*6777b538SAndroid Build Coastguard Worker reader_thread_runner_ = std::make_unique<ReaderThreadRunner>(
169*6777b538SAndroid Build Coastguard Worker pipe_,
170*6777b538SAndroid Build Coastguard Worker base::BindRepeating(&ChannelNacl::DidRecvMsg,
171*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()),
172*6777b538SAndroid Build Coastguard Worker base::BindRepeating(&ChannelNacl::ReadDidFail,
173*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()),
174*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault());
175*6777b538SAndroid Build Coastguard Worker reader_thread_ = std::make_unique<base::DelegateSimpleThread>(
176*6777b538SAndroid Build Coastguard Worker reader_thread_runner_.get(), "ipc_channel_nacl reader thread");
177*6777b538SAndroid Build Coastguard Worker reader_thread_->Start();
178*6777b538SAndroid Build Coastguard Worker waiting_connect_ = false;
179*6777b538SAndroid Build Coastguard Worker // If there were any messages queued before connection, send them.
180*6777b538SAndroid Build Coastguard Worker ProcessOutgoingMessages();
181*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
182*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&ChannelNacl::CallOnChannelConnected,
183*6777b538SAndroid Build Coastguard Worker weak_ptr_factory_.GetWeakPtr()));
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker return true;
186*6777b538SAndroid Build Coastguard Worker }
187*6777b538SAndroid Build Coastguard Worker
Close()188*6777b538SAndroid Build Coastguard Worker void ChannelNacl::Close() {
189*6777b538SAndroid Build Coastguard Worker // For now, we assume that at shutdown, the reader thread will be woken with
190*6777b538SAndroid Build Coastguard Worker // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we
191*6777b538SAndroid Build Coastguard Worker // might simply be killed with no chance to clean up anyway :-).
192*6777b538SAndroid Build Coastguard Worker // If untrusted code tries to close the channel prior to shutdown, it's likely
193*6777b538SAndroid Build Coastguard Worker // to hang.
194*6777b538SAndroid Build Coastguard Worker // TODO(dmichael): Can we do anything smarter here to make sure the reader
195*6777b538SAndroid Build Coastguard Worker // thread wakes up and quits?
196*6777b538SAndroid Build Coastguard Worker reader_thread_->Join();
197*6777b538SAndroid Build Coastguard Worker close(pipe_);
198*6777b538SAndroid Build Coastguard Worker pipe_ = -1;
199*6777b538SAndroid Build Coastguard Worker reader_thread_runner_.reset();
200*6777b538SAndroid Build Coastguard Worker reader_thread_.reset();
201*6777b538SAndroid Build Coastguard Worker read_queue_.clear();
202*6777b538SAndroid Build Coastguard Worker output_queue_.clear();
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker
Send(Message * message)205*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::Send(Message* message) {
206*6777b538SAndroid Build Coastguard Worker DCHECK(!message->HasAttachments());
207*6777b538SAndroid Build Coastguard Worker DVLOG(2) << "sending message @" << message << " on channel @" << this
208*6777b538SAndroid Build Coastguard Worker << " with type " << message->type();
209*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Message> message_ptr(message);
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
212*6777b538SAndroid Build Coastguard Worker Logging::GetInstance()->OnSendMessage(message_ptr.get());
213*6777b538SAndroid Build Coastguard Worker #endif // BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker TRACE_EVENT_WITH_FLOW0("toplevel.flow", "ChannelNacl::Send",
216*6777b538SAndroid Build Coastguard Worker message->header()->flags, TRACE_EVENT_FLAG_FLOW_OUT);
217*6777b538SAndroid Build Coastguard Worker output_queue_.push_back(std::move(message_ptr));
218*6777b538SAndroid Build Coastguard Worker if (!waiting_connect_)
219*6777b538SAndroid Build Coastguard Worker return ProcessOutgoingMessages();
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Worker return true;
222*6777b538SAndroid Build Coastguard Worker }
223*6777b538SAndroid Build Coastguard Worker
DidRecvMsg(std::unique_ptr<MessageContents> contents)224*6777b538SAndroid Build Coastguard Worker void ChannelNacl::DidRecvMsg(std::unique_ptr<MessageContents> contents) {
225*6777b538SAndroid Build Coastguard Worker // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from
226*6777b538SAndroid Build Coastguard Worker // the reader thread after Close is called. If so, we ignore it.
227*6777b538SAndroid Build Coastguard Worker if (pipe_ == -1)
228*6777b538SAndroid Build Coastguard Worker return;
229*6777b538SAndroid Build Coastguard Worker
230*6777b538SAndroid Build Coastguard Worker auto data = std::make_unique<std::vector<char>>();
231*6777b538SAndroid Build Coastguard Worker data->swap(contents->data);
232*6777b538SAndroid Build Coastguard Worker read_queue_.push_back(std::move(data));
233*6777b538SAndroid Build Coastguard Worker
234*6777b538SAndroid Build Coastguard Worker input_attachments_.reserve(contents->fds.size());
235*6777b538SAndroid Build Coastguard Worker for (int fd : contents->fds) {
236*6777b538SAndroid Build Coastguard Worker input_attachments_.push_back(
237*6777b538SAndroid Build Coastguard Worker new internal::PlatformFileAttachment(base::ScopedFD(fd)));
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker contents->fds.clear();
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker // In POSIX, we would be told when there are bytes to read by implementing
242*6777b538SAndroid Build Coastguard Worker // OnFileCanReadWithoutBlocking in MessagePumpForIO::FdWatcher. In NaCl, we
243*6777b538SAndroid Build Coastguard Worker // instead know at this point because the reader thread posted some data to
244*6777b538SAndroid Build Coastguard Worker // us.
245*6777b538SAndroid Build Coastguard Worker ProcessIncomingMessages();
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker
ReadDidFail()248*6777b538SAndroid Build Coastguard Worker void ChannelNacl::ReadDidFail() {
249*6777b538SAndroid Build Coastguard Worker Close();
250*6777b538SAndroid Build Coastguard Worker }
251*6777b538SAndroid Build Coastguard Worker
CreatePipe(const IPC::ChannelHandle & channel_handle)252*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::CreatePipe(
253*6777b538SAndroid Build Coastguard Worker const IPC::ChannelHandle& channel_handle) {
254*6777b538SAndroid Build Coastguard Worker DCHECK(pipe_ == -1);
255*6777b538SAndroid Build Coastguard Worker
256*6777b538SAndroid Build Coastguard Worker // There's one possible case in NaCl:
257*6777b538SAndroid Build Coastguard Worker // 1) It's a channel wrapping a pipe that is given to us.
258*6777b538SAndroid Build Coastguard Worker // We don't support these:
259*6777b538SAndroid Build Coastguard Worker // 2) It's for a named channel.
260*6777b538SAndroid Build Coastguard Worker // 3) It's for a client that we implement ourself.
261*6777b538SAndroid Build Coastguard Worker // 4) It's the initial IPC channel.
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker if (channel_handle.socket.fd == -1) {
264*6777b538SAndroid Build Coastguard Worker NOTIMPLEMENTED();
265*6777b538SAndroid Build Coastguard Worker return false;
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker pipe_ = channel_handle.socket.fd;
268*6777b538SAndroid Build Coastguard Worker return true;
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker
ProcessOutgoingMessages()271*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::ProcessOutgoingMessages() {
272*6777b538SAndroid Build Coastguard Worker DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
273*6777b538SAndroid Build Coastguard Worker // no connection?
274*6777b538SAndroid Build Coastguard Worker if (output_queue_.empty())
275*6777b538SAndroid Build Coastguard Worker return true;
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Worker if (pipe_ == -1)
278*6777b538SAndroid Build Coastguard Worker return false;
279*6777b538SAndroid Build Coastguard Worker
280*6777b538SAndroid Build Coastguard Worker // Write out all the messages. The trusted implementation is guaranteed to not
281*6777b538SAndroid Build Coastguard Worker // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg.
282*6777b538SAndroid Build Coastguard Worker while (!output_queue_.empty()) {
283*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Message> msg = std::move(output_queue_.front());
284*6777b538SAndroid Build Coastguard Worker output_queue_.pop_front();
285*6777b538SAndroid Build Coastguard Worker
286*6777b538SAndroid Build Coastguard Worker const size_t num_fds = msg->attachment_set()->size();
287*6777b538SAndroid Build Coastguard Worker DCHECK(num_fds <= MessageAttachmentSet::kMaxDescriptorsPerMessage);
288*6777b538SAndroid Build Coastguard Worker std::vector<int> fds;
289*6777b538SAndroid Build Coastguard Worker fds.reserve(num_fds);
290*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < num_fds; i++) {
291*6777b538SAndroid Build Coastguard Worker scoped_refptr<MessageAttachment> attachment =
292*6777b538SAndroid Build Coastguard Worker msg->attachment_set()->GetAttachmentAt(i);
293*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(MessageAttachment::Type::PLATFORM_FILE, attachment->GetType());
294*6777b538SAndroid Build Coastguard Worker fds.push_back(static_cast<internal::PlatformFileAttachment&>(*attachment)
295*6777b538SAndroid Build Coastguard Worker .TakePlatformFile());
296*6777b538SAndroid Build Coastguard Worker }
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker NaClAbiNaClImcMsgIoVec iov = {const_cast<uint8_t*>(msg->data()),
299*6777b538SAndroid Build Coastguard Worker msg->size()};
300*6777b538SAndroid Build Coastguard Worker NaClAbiNaClImcMsgHdr msgh = {&iov, 1, fds.data(), num_fds};
301*6777b538SAndroid Build Coastguard Worker ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0);
302*6777b538SAndroid Build Coastguard Worker
303*6777b538SAndroid Build Coastguard Worker DCHECK(bytes_written); // The trusted side shouldn't return 0.
304*6777b538SAndroid Build Coastguard Worker if (bytes_written < 0) {
305*6777b538SAndroid Build Coastguard Worker // The trusted side should only ever give us an error of EPIPE. We
306*6777b538SAndroid Build Coastguard Worker // should never be interrupted, nor should we get EAGAIN.
307*6777b538SAndroid Build Coastguard Worker DCHECK(errno == EPIPE);
308*6777b538SAndroid Build Coastguard Worker Close();
309*6777b538SAndroid Build Coastguard Worker PLOG(ERROR) << "pipe_ error on "
310*6777b538SAndroid Build Coastguard Worker << pipe_
311*6777b538SAndroid Build Coastguard Worker << " Currently writing message of size: "
312*6777b538SAndroid Build Coastguard Worker << msg->size();
313*6777b538SAndroid Build Coastguard Worker return false;
314*6777b538SAndroid Build Coastguard Worker } else {
315*6777b538SAndroid Build Coastguard Worker msg->attachment_set()->CommitAllDescriptors();
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker
318*6777b538SAndroid Build Coastguard Worker // Message sent OK!
319*6777b538SAndroid Build Coastguard Worker DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type()
320*6777b538SAndroid Build Coastguard Worker << " on fd " << pipe_;
321*6777b538SAndroid Build Coastguard Worker }
322*6777b538SAndroid Build Coastguard Worker return true;
323*6777b538SAndroid Build Coastguard Worker }
324*6777b538SAndroid Build Coastguard Worker
CallOnChannelConnected()325*6777b538SAndroid Build Coastguard Worker void ChannelNacl::CallOnChannelConnected() {
326*6777b538SAndroid Build Coastguard Worker listener()->OnChannelConnected(-1);
327*6777b538SAndroid Build Coastguard Worker }
328*6777b538SAndroid Build Coastguard Worker
ReadData(char * buffer,int buffer_len,int * bytes_read)329*6777b538SAndroid Build Coastguard Worker ChannelNacl::ReadState ChannelNacl::ReadData(
330*6777b538SAndroid Build Coastguard Worker char* buffer,
331*6777b538SAndroid Build Coastguard Worker int buffer_len,
332*6777b538SAndroid Build Coastguard Worker int* bytes_read) {
333*6777b538SAndroid Build Coastguard Worker *bytes_read = 0;
334*6777b538SAndroid Build Coastguard Worker if (pipe_ == -1)
335*6777b538SAndroid Build Coastguard Worker return READ_FAILED;
336*6777b538SAndroid Build Coastguard Worker if (read_queue_.empty())
337*6777b538SAndroid Build Coastguard Worker return READ_PENDING;
338*6777b538SAndroid Build Coastguard Worker while (!read_queue_.empty() && *bytes_read < buffer_len) {
339*6777b538SAndroid Build Coastguard Worker std::vector<char>* vec = read_queue_.front().get();
340*6777b538SAndroid Build Coastguard Worker size_t bytes_to_read = buffer_len - *bytes_read;
341*6777b538SAndroid Build Coastguard Worker if (vec->size() <= bytes_to_read) {
342*6777b538SAndroid Build Coastguard Worker // We can read and discard the entire vector.
343*6777b538SAndroid Build Coastguard Worker base::ranges::copy(*vec, buffer + *bytes_read);
344*6777b538SAndroid Build Coastguard Worker *bytes_read += vec->size();
345*6777b538SAndroid Build Coastguard Worker read_queue_.pop_front();
346*6777b538SAndroid Build Coastguard Worker } else {
347*6777b538SAndroid Build Coastguard Worker // Read all the bytes we can and discard them from the front of the
348*6777b538SAndroid Build Coastguard Worker // vector. (This can be slowish, since erase has to move the back of the
349*6777b538SAndroid Build Coastguard Worker // vector to the front, but it's hopefully a temporary hack and it keeps
350*6777b538SAndroid Build Coastguard Worker // the code simple).
351*6777b538SAndroid Build Coastguard Worker std::copy(vec->begin(), vec->begin() + bytes_to_read,
352*6777b538SAndroid Build Coastguard Worker buffer + *bytes_read);
353*6777b538SAndroid Build Coastguard Worker vec->erase(vec->begin(), vec->begin() + bytes_to_read);
354*6777b538SAndroid Build Coastguard Worker *bytes_read += bytes_to_read;
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker }
357*6777b538SAndroid Build Coastguard Worker return READ_SUCCEEDED;
358*6777b538SAndroid Build Coastguard Worker }
359*6777b538SAndroid Build Coastguard Worker
ShouldDispatchInputMessage(Message * msg)360*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::ShouldDispatchInputMessage(Message* msg) {
361*6777b538SAndroid Build Coastguard Worker return true;
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker
GetAttachments(Message * msg)364*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::GetAttachments(Message* msg) {
365*6777b538SAndroid Build Coastguard Worker uint16_t header_fds = msg->header()->num_fds;
366*6777b538SAndroid Build Coastguard Worker CHECK(header_fds == input_attachments_.size());
367*6777b538SAndroid Build Coastguard Worker if (header_fds == 0)
368*6777b538SAndroid Build Coastguard Worker return true; // Nothing to do.
369*6777b538SAndroid Build Coastguard Worker
370*6777b538SAndroid Build Coastguard Worker for (auto& attachment : input_attachments_) {
371*6777b538SAndroid Build Coastguard Worker msg->attachment_set()->AddAttachment(std::move(attachment));
372*6777b538SAndroid Build Coastguard Worker }
373*6777b538SAndroid Build Coastguard Worker input_attachments_.clear();
374*6777b538SAndroid Build Coastguard Worker return true;
375*6777b538SAndroid Build Coastguard Worker }
376*6777b538SAndroid Build Coastguard Worker
DidEmptyInputBuffers()377*6777b538SAndroid Build Coastguard Worker bool ChannelNacl::DidEmptyInputBuffers() {
378*6777b538SAndroid Build Coastguard Worker // When the input data buffer is empty, the attachments should be too.
379*6777b538SAndroid Build Coastguard Worker return input_attachments_.empty();
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker
HandleInternalMessage(const Message & msg)382*6777b538SAndroid Build Coastguard Worker void ChannelNacl::HandleInternalMessage(const Message& msg) {
383*6777b538SAndroid Build Coastguard Worker // The trusted side IPC::Channel should handle the "hello" handshake; we
384*6777b538SAndroid Build Coastguard Worker // should not receive the "Hello" message.
385*6777b538SAndroid Build Coastguard Worker NOTREACHED();
386*6777b538SAndroid Build Coastguard Worker }
387*6777b538SAndroid Build Coastguard Worker
388*6777b538SAndroid Build Coastguard Worker // Channel's methods
389*6777b538SAndroid Build Coastguard Worker
390*6777b538SAndroid Build Coastguard Worker // static
Create(const IPC::ChannelHandle & channel_handle,Mode mode,Listener * listener)391*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Channel> Channel::Create(
392*6777b538SAndroid Build Coastguard Worker const IPC::ChannelHandle& channel_handle,
393*6777b538SAndroid Build Coastguard Worker Mode mode,
394*6777b538SAndroid Build Coastguard Worker Listener* listener) {
395*6777b538SAndroid Build Coastguard Worker return std::make_unique<ChannelNacl>(channel_handle, mode, listener);
396*6777b538SAndroid Build Coastguard Worker }
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker } // namespace IPC
399