ipc_channel_nacl.cc 13 KB

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