blob: 4984572c6ba0e4f95fffe871f7abf8e30ece3344 [file] [log] [blame]
[email protected]ce208f872012-03-07 20:42:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]c2f10ed2009-02-10 00:52:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "build/build_config.h"
6
[email protected]3c788582013-01-25 21:51:357#if defined(OS_POSIX)
[email protected]e8351b7e2009-02-10 22:25:398#if defined(OS_MACOSX)
9extern "C" {
10#include <sandbox.h>
Nico Webere86ed9b32019-02-22 18:11:1211}
[email protected]e8351b7e2009-02-10 22:25:3912#endif
[email protected]d67c2492009-03-20 17:26:0213#include <fcntl.h>
avi246998d82015-12-22 02:39:0414#include <stddef.h>
[email protected]dc875dc2013-10-15 00:07:0015#include <sys/socket.h>
[email protected]c2f10ed2009-02-10 00:52:5716#include <sys/stat.h>
[email protected]3c788582013-01-25 21:51:3517#include <unistd.h>
[email protected]c2f10ed2009-02-10 00:52:5718
danakj03de39b22016-04-23 04:21:0919#include <memory>
[email protected]dc875dc2013-10-15 00:07:0020#include <queue>
21
22#include "base/callback.h"
[email protected]7a4de7a62010-08-17 18:38:2423#include "base/file_descriptor_posix.h"
skyostile687bdff2015-05-12 11:29:2124#include "base/location.h"
[email protected]3c788582013-01-25 21:51:3525#include "base/pickle.h"
26#include "base/posix/eintr_wrapper.h"
fdoray8e32586852016-06-22 19:56:1627#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2128#include "base/single_thread_task_runner.h"
[email protected]dc875dc2013-10-15 00:07:0029#include "base/synchronization/waitable_event.h"
gab4d92485f2016-09-26 21:00:4530#include "base/threading/thread.h"
rockota34707ca2016-07-20 04:28:3231#include "base/threading/thread_task_runner_handle.h"
morrita4b5c28e22015-01-14 21:17:0632#include "ipc/ipc_message_attachment_set.h"
[email protected]3c788582013-01-25 21:51:3533#include "ipc/ipc_message_utils.h"
34#include "ipc/ipc_test_base.h"
[email protected]c2f10ed2009-02-10 00:52:5735
yusukesd0329fc2015-01-06 06:56:3436#if defined(OS_POSIX)
37#include "base/macros.h"
yusukesd0329fc2015-01-06 06:56:3438#endif
39
kerrneldc059fe2016-04-12 16:39:0640#if defined(OS_MACOSX)
41#include "sandbox/mac/seatbelt.h"
42#endif
43
[email protected]e8351b7e2009-02-10 22:25:3944namespace {
45
yusukesc986c5432015-05-06 19:45:4546const unsigned kNumFDsToSend = 7; // per message
47const unsigned kNumMessages = 20;
[email protected]926394462009-02-11 23:23:1248const char* kDevZeroPath = "/dev/zero";
[email protected]e8351b7e2009-02-10 22:25:3949
Fabrice de Gans-Riberi894661c2018-05-24 18:43:2250#if defined(OS_POSIX) || defined(OS_FUCHSIA)
anujk.sharma5a7ffe2f2015-01-22 05:39:3751static_assert(kNumFDsToSend ==
52 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage,
53 "The number of FDs to send must be kMaxDescriptorsPerMessage.");
yusukesd0329fc2015-01-06 06:56:3454#endif
55
[email protected]dc875dc2013-10-15 00:07:0056class MyChannelDescriptorListenerBase : public IPC::Listener {
[email protected]c2f10ed2009-02-10 00:52:5757 public:
dchengfe61fca2014-10-22 02:29:5258 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2559 base::PickleIterator iter(message);
[email protected]5fe733de2009-02-11 18:59:2060 base::FileDescriptor descriptor;
yusukesd0329fc2015-01-06 06:56:3461 while (IPC::ParamTraits<base::FileDescriptor>::Read(
62 &message, &iter, &descriptor)) {
63 HandleFD(descriptor.fd);
64 }
[email protected]a95986a82010-12-24 06:19:2865 return true;
[email protected]c2f10ed2009-02-10 00:52:5766 }
67
[email protected]dc875dc2013-10-15 00:07:0068 protected:
69 virtual void HandleFD(int fd) = 0;
70};
71
72class MyChannelDescriptorListener : public MyChannelDescriptorListenerBase {
73 public:
74 explicit MyChannelDescriptorListener(ino_t expected_inode_num)
75 : MyChannelDescriptorListenerBase(),
76 expected_inode_num_(expected_inode_num),
77 num_fds_received_(0) {
[email protected]6b47b4d2013-10-10 21:12:1478 }
79
sammc6ed3efb2016-11-23 03:17:3580 unsigned num_fds_received() const {
81 return num_fds_received_;
[email protected]6b47b4d2013-10-10 21:12:1482 }
83
dchengfe61fca2014-10-22 02:29:5284 void OnChannelError() override {
Gabriel Charette53a9ef812017-07-26 12:36:2385 base::RunLoop::QuitCurrentWhenIdleDeprecated();
dchengf3076af2014-10-21 18:02:4286 }
[email protected]dc875dc2013-10-15 00:07:0087
88 protected:
dchengfe61fca2014-10-22 02:29:5289 void HandleFD(int fd) override {
yusukesd0329fc2015-01-06 06:56:3490 ASSERT_GE(fd, 0);
[email protected]dc875dc2013-10-15 00:07:0091 // Check that we can read from the FD.
92 char buf;
93 ssize_t amt_read = read(fd, &buf, 1);
94 ASSERT_EQ(amt_read, 1);
95 ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
96
97 struct stat st;
98 ASSERT_EQ(fstat(fd, &st), 0);
99
100 ASSERT_EQ(close(fd), 0);
101
102 // Compare inode numbers to check that the file sent over the wire is
103 // actually the one expected.
104 ASSERT_EQ(expected_inode_num_, st.st_ino);
105
106 ++num_fds_received_;
yusukesd0329fc2015-01-06 06:56:34107 if (num_fds_received_ == kNumFDsToSend * kNumMessages)
Gabriel Charette53a9ef812017-07-26 12:36:23108 base::RunLoop::QuitCurrentWhenIdleDeprecated();
[email protected]dc875dc2013-10-15 00:07:00109 }
110
[email protected]e8351b7e2009-02-10 22:25:39111 private:
112 ino_t expected_inode_num_;
[email protected]926394462009-02-11 23:23:12113 unsigned num_fds_received_;
[email protected]c2f10ed2009-02-10 00:52:57114};
115
sammc4bcc4ed62016-10-27 10:13:59116class IPCSendFdsTest : public IPCChannelMojoTestBase {
[email protected]3c788582013-01-25 21:51:35117 protected:
118 void RunServer() {
119 // Set up IPC channel and start client.
120 MyChannelDescriptorListener listener(-1);
121 CreateChannel(&listener);
122 ASSERT_TRUE(ConnectChannel());
[email protected]c2f10ed2009-02-10 00:52:57123
yusukesd0329fc2015-01-06 06:56:34124 for (unsigned i = 0; i < kNumMessages; ++i) {
[email protected]753bb252013-11-04 22:28:12125 IPC::Message* message =
126 new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
yusukesd0329fc2015-01-06 06:56:34127 for (unsigned j = 0; j < kNumFDsToSend; ++j) {
128 const int fd = open(kDevZeroPath, O_RDONLY);
129 ASSERT_GE(fd, 0);
130 base::FileDescriptor descriptor(fd, true);
131 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
132 }
[email protected]3c788582013-01-25 21:51:35133 ASSERT_TRUE(sender()->Send(message));
134 }
135
136 // Run message loop.
fdoray8e32586852016-06-22 19:56:16137 base::RunLoop().Run();
[email protected]3c788582013-01-25 21:51:35138
139 // Close the channel so the client's OnChannelError() gets fired.
140 channel()->Close();
141
142 EXPECT_TRUE(WaitForClientShutdown());
143 DestroyChannel();
[email protected]926394462009-02-11 23:23:12144 }
[email protected]3c788582013-01-25 21:51:35145};
146
amistry6de2ee4f2016-05-05 05:12:09147TEST_F(IPCSendFdsTest, DescriptorTest) {
[email protected]3c788582013-01-25 21:51:35148 Init("SendFdsClient");
149 RunServer();
150}
151
sammc4bcc4ed62016-10-27 10:13:59152class SendFdsTestClientFixture : public IpcChannelMojoTestClient {
153 protected:
154 void SendFdsClientCommon(const std::string& test_client_name,
155 ino_t expected_inode_num) {
156 MyChannelDescriptorListener listener(expected_inode_num);
[email protected]3c788582013-01-25 21:51:35157
sammc4bcc4ed62016-10-27 10:13:59158 // Set up IPC channel.
159 Connect(&listener);
[email protected]c2f10ed2009-02-10 00:52:57160
sammc4bcc4ed62016-10-27 10:13:59161 // Run message loop.
162 base::RunLoop().Run();
[email protected]c2f10ed2009-02-10 00:52:57163
sammc4bcc4ed62016-10-27 10:13:59164 // Verify that the message loop was exited due to getting the correct number
165 // of descriptors, and not because of the channel closing unexpectedly.
sammc6ed3efb2016-11-23 03:17:35166 EXPECT_EQ(kNumFDsToSend * kNumMessages, listener.num_fds_received());
[email protected]d484ab52010-12-09 01:12:20167
sammc4bcc4ed62016-10-27 10:13:59168 Close();
169 }
170};
[email protected]e8351b7e2009-02-10 22:25:39171
sammc4bcc4ed62016-10-27 10:13:59172DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
173 SendFdsClient,
174 SendFdsTestClientFixture) {
[email protected]3c788582013-01-25 21:51:35175 struct stat st;
176 int fd = open(kDevZeroPath, O_RDONLY);
177 fstat(fd, &st);
[email protected]d89eec82013-12-03 14:10:59178 EXPECT_GE(IGNORE_EINTR(close(fd)), 0);
sammc4bcc4ed62016-10-27 10:13:59179 SendFdsClientCommon("SendFdsClient", st.st_ino);
[email protected]3c788582013-01-25 21:51:35180}
[email protected]0cb7d8c82013-01-11 15:13:37181
[email protected]e8351b7e2009-02-10 22:25:39182#if defined(OS_MACOSX)
[email protected]3c788582013-01-25 21:51:35183// Test that FDs are correctly sent to a sandboxed process.
[email protected]e8351b7e2009-02-10 22:25:39184// TODO(port): Make this test cross-platform.
[email protected]3c788582013-01-25 21:51:35185TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
186 Init("SendFdsSandboxedClient");
187 RunServer();
188}
189
sammc4bcc4ed62016-10-27 10:13:59190DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
191 SendFdsSandboxedClient,
192 SendFdsTestClientFixture) {
[email protected]e8351b7e2009-02-10 22:25:39193 struct stat st;
[email protected]926394462009-02-11 23:23:12194 const int fd = open(kDevZeroPath, O_RDONLY);
[email protected]e8351b7e2009-02-10 22:25:39195 fstat(fd, &st);
sammc4bcc4ed62016-10-27 10:13:59196 ASSERT_LE(0, IGNORE_EINTR(close(fd)));
[email protected]e8351b7e2009-02-10 22:25:39197
[email protected]3c788582013-01-25 21:51:35198 // Enable the sandbox.
[email protected]e8351b7e2009-02-10 22:25:39199 char* error_buff = NULL;
kerrneldf7ac7462016-09-24 00:39:26200 int error = sandbox::Seatbelt::Init(
201 sandbox::Seatbelt::kProfilePureComputation, SANDBOX_NAMED, &error_buff);
sammc4bcc4ed62016-10-27 10:13:59202 ASSERT_EQ(0, error);
203 ASSERT_FALSE(error_buff);
[email protected]e8351b7e2009-02-10 22:25:39204
kerrneldc059fe2016-04-12 16:39:06205 sandbox::Seatbelt::FreeError(error_buff);
[email protected]e8351b7e2009-02-10 22:25:39206
[email protected]3c788582013-01-25 21:51:35207 // Make sure sandbox is really enabled.
sammc4bcc4ed62016-10-27 10:13:59208 ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY))
209 << "Sandbox wasn't properly enabled";
[email protected]e8351b7e2009-02-10 22:25:39210
211 // See if we can receive a file descriptor.
sammc4bcc4ed62016-10-27 10:13:59212 SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
[email protected]e8351b7e2009-02-10 22:25:39213}
214#endif // defined(OS_MACOSX)
215
[email protected]2a3aa7b52013-01-11 20:56:22216} // namespace
217
[email protected]c2f10ed2009-02-10 00:52:57218#endif // defined(OS_POSIX)