[go: nahoru, domu]

blob: 0523d9b47edb67cfdaa4faad29c2567f9a0267bb [file] [log] [blame]
jbates@chromium.orgce208f872012-03-07 20:42:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
jeremy@chromium.orgc2f10ed2009-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
Greg Thompsonbec327a72021-11-10 16:31:485#include "build/os_buildflags.h"
jeremy@chromium.orgc2f10ed2009-02-10 00:52:576
Greg Thompsonbec327a72021-11-10 16:31:487#if BUILDFLAG(IS_MAC)
jeremy@chromium.orge8351b7e2009-02-10 22:25:398extern "C" {
9#include <sandbox.h>
Nico Webere86ed9b32019-02-22 18:11:1210}
jeremy@chromium.orge8351b7e2009-02-10 22:25:3911#endif
Greg Thompsonbec327a72021-11-10 16:31:4812
patrick@chromium.orgd67c2492009-03-20 17:26:0213#include <fcntl.h>
avi246998d2015-12-22 02:39:0414#include <stddef.h>
hubbe@chromium.orgdc875dc2013-10-15 00:07:0015#include <sys/socket.h>
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5716#include <sys/stat.h>
viettrungluu@chromium.org3c788582013-01-25 21:51:3517#include <unistd.h>
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5718
danakj03de39b2016-04-23 04:21:0919#include <memory>
hubbe@chromium.orgdc875dc2013-10-15 00:07:0020#include <queue>
21
erg@google.com7a4de7a62010-08-17 18:38:2422#include "base/file_descriptor_posix.h"
viettrungluu@chromium.org3c788582013-01-25 21:51:3523#include "base/pickle.h"
24#include "base/posix/eintr_wrapper.h"
fdoray8e32586852016-06-22 19:56:1625#include "base/run_loop.h"
hubbe@chromium.orgdc875dc2013-10-15 00:07:0026#include "base/synchronization/waitable_event.h"
Patrick Monette643cdf62021-10-15 19:13:4227#include "base/task/single_thread_task_runner.h"
gab4d92485f2016-09-26 21:00:4528#include "base/threading/thread.h"
rockota34707ca2016-07-20 04:28:3229#include "base/threading/thread_task_runner_handle.h"
morrita4b5c28e22015-01-14 21:17:0630#include "ipc/ipc_message_attachment_set.h"
viettrungluu@chromium.org3c788582013-01-25 21:51:3531#include "ipc/ipc_message_utils.h"
32#include "ipc/ipc_test_base.h"
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5733
Greg Thompsonbec327a72021-11-10 16:31:4834#if BUILDFLAG(IS_MAC)
kerrneldc059fe2016-04-12 16:39:0635#include "sandbox/mac/seatbelt.h"
Greg Thompson9360c5d42021-12-01 17:55:3436#elif BUILDFLAG(IS_FUCHSIA)
37#include "base/memory/scoped_refptr.h"
38#include "base/test/scoped_dev_zero_fuchsia.h"
kerrneldc059fe2016-04-12 16:39:0639#endif
40
jeremy@chromium.orge8351b7e2009-02-10 22:25:3941namespace {
42
yusukesc986c5432015-05-06 19:45:4543const unsigned kNumFDsToSend = 7; // per message
44const unsigned kNumMessages = 20;
agl@chromium.org926394462009-02-11 23:23:1245const char* kDevZeroPath = "/dev/zero";
jeremy@chromium.orge8351b7e2009-02-10 22:25:3946
anujk.sharma5a7ffe2f2015-01-22 05:39:3747static_assert(kNumFDsToSend ==
48 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage,
49 "The number of FDs to send must be kMaxDescriptorsPerMessage.");
yusukesd0329fc2015-01-06 06:56:3450
hubbe@chromium.orgdc875dc2013-10-15 00:07:0051class MyChannelDescriptorListenerBase : public IPC::Listener {
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5752 public:
dchengfe61fca2014-10-22 02:29:5253 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2554 base::PickleIterator iter(message);
agl@chromium.org5fe733de2009-02-11 18:59:2055 base::FileDescriptor descriptor;
yusukesd0329fc2015-01-06 06:56:3456 while (IPC::ParamTraits<base::FileDescriptor>::Read(
57 &message, &iter, &descriptor)) {
58 HandleFD(descriptor.fd);
59 }
jam@chromium.orga95986a2010-12-24 06:19:2860 return true;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5761 }
62
hubbe@chromium.orgdc875dc2013-10-15 00:07:0063 protected:
64 virtual void HandleFD(int fd) = 0;
65};
66
67class MyChannelDescriptorListener : public MyChannelDescriptorListenerBase {
68 public:
69 explicit MyChannelDescriptorListener(ino_t expected_inode_num)
70 : MyChannelDescriptorListenerBase(),
71 expected_inode_num_(expected_inode_num),
72 num_fds_received_(0) {
hubbe@chromium.org6b47b4d2013-10-10 21:12:1473 }
74
sammc6ed3efb2016-11-23 03:17:3575 unsigned num_fds_received() const {
76 return num_fds_received_;
hubbe@chromium.org6b47b4d2013-10-10 21:12:1477 }
78
dchengfe61fca2014-10-22 02:29:5279 void OnChannelError() override {
Gabriel Charette53a9ef812017-07-26 12:36:2380 base::RunLoop::QuitCurrentWhenIdleDeprecated();
dchengf3076af2014-10-21 18:02:4281 }
hubbe@chromium.orgdc875dc2013-10-15 00:07:0082
83 protected:
dchengfe61fca2014-10-22 02:29:5284 void HandleFD(int fd) override {
yusukesd0329fc2015-01-06 06:56:3485 ASSERT_GE(fd, 0);
hubbe@chromium.orgdc875dc2013-10-15 00:07:0086 // Check that we can read from the FD.
87 char buf;
88 ssize_t amt_read = read(fd, &buf, 1);
89 ASSERT_EQ(amt_read, 1);
90 ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
91
92 struct stat st;
93 ASSERT_EQ(fstat(fd, &st), 0);
94
95 ASSERT_EQ(close(fd), 0);
96
97 // Compare inode numbers to check that the file sent over the wire is
98 // actually the one expected.
99 ASSERT_EQ(expected_inode_num_, st.st_ino);
100
101 ++num_fds_received_;
yusukesd0329fc2015-01-06 06:56:34102 if (num_fds_received_ == kNumFDsToSend * kNumMessages)
Gabriel Charette53a9ef812017-07-26 12:36:23103 base::RunLoop::QuitCurrentWhenIdleDeprecated();
hubbe@chromium.orgdc875dc2013-10-15 00:07:00104 }
105
jeremy@chromium.orge8351b7e2009-02-10 22:25:39106 private:
107 ino_t expected_inode_num_;
agl@chromium.org926394462009-02-11 23:23:12108 unsigned num_fds_received_;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57109};
110
sammc4bcc4ed62016-10-27 10:13:59111class IPCSendFdsTest : public IPCChannelMojoTestBase {
viettrungluu@chromium.org3c788582013-01-25 21:51:35112 protected:
Greg Thompson9360c5d42021-12-01 17:55:34113 void SetUp() override {
114#if BUILDFLAG(IS_FUCHSIA)
115 ASSERT_TRUE(dev_zero_);
116#endif
117 }
118
viettrungluu@chromium.org3c788582013-01-25 21:51:35119 void RunServer() {
120 // Set up IPC channel and start client.
121 MyChannelDescriptorListener listener(-1);
122 CreateChannel(&listener);
123 ASSERT_TRUE(ConnectChannel());
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57124
yusukesd0329fc2015-01-06 06:56:34125 for (unsigned i = 0; i < kNumMessages; ++i) {
bbudge@chromium.org753bb252013-11-04 22:28:12126 IPC::Message* message =
127 new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
yusukesd0329fc2015-01-06 06:56:34128 for (unsigned j = 0; j < kNumFDsToSend; ++j) {
129 const int fd = open(kDevZeroPath, O_RDONLY);
130 ASSERT_GE(fd, 0);
131 base::FileDescriptor descriptor(fd, true);
132 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
133 }
viettrungluu@chromium.org3c788582013-01-25 21:51:35134 ASSERT_TRUE(sender()->Send(message));
135 }
136
137 // Run message loop.
fdoray8e32586852016-06-22 19:56:16138 base::RunLoop().Run();
viettrungluu@chromium.org3c788582013-01-25 21:51:35139
140 // Close the channel so the client's OnChannelError() gets fired.
141 channel()->Close();
142
143 EXPECT_TRUE(WaitForClientShutdown());
144 DestroyChannel();
agl@chromium.org926394462009-02-11 23:23:12145 }
Greg Thompson9360c5d42021-12-01 17:55:34146
147 private:
148#if BUILDFLAG(IS_FUCHSIA)
149 scoped_refptr<base::ScopedDevZero> dev_zero_ = base::ScopedDevZero::Get();
150#endif
viettrungluu@chromium.org3c788582013-01-25 21:51:35151};
152
Greg Thompson9360c5d42021-12-01 17:55:34153// Disabled on Fuchsia due to failures; see https://crbug.com/1272424.
154#if BUILDFLAG(IS_FUCHSIA)
155#define MAYBE_DescriptorTest DISABLED_DescriptorTest
156#else
157#define MAYBE_DescriptorTest DescriptorTest
158#endif
159TEST_F(IPCSendFdsTest, MAYBE_DescriptorTest) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35160 Init("SendFdsClient");
161 RunServer();
162}
163
sammc4bcc4ed62016-10-27 10:13:59164class SendFdsTestClientFixture : public IpcChannelMojoTestClient {
165 protected:
166 void SendFdsClientCommon(const std::string& test_client_name,
167 ino_t expected_inode_num) {
168 MyChannelDescriptorListener listener(expected_inode_num);
viettrungluu@chromium.org3c788582013-01-25 21:51:35169
sammc4bcc4ed62016-10-27 10:13:59170 // Set up IPC channel.
171 Connect(&listener);
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57172
sammc4bcc4ed62016-10-27 10:13:59173 // Run message loop.
174 base::RunLoop().Run();
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57175
sammc4bcc4ed62016-10-27 10:13:59176 // Verify that the message loop was exited due to getting the correct number
177 // of descriptors, and not because of the channel closing unexpectedly.
sammc6ed3efb2016-11-23 03:17:35178 EXPECT_EQ(kNumFDsToSend * kNumMessages, listener.num_fds_received());
dmaclach@chromium.orgd484ab52010-12-09 01:12:20179
sammc4bcc4ed62016-10-27 10:13:59180 Close();
181 }
182};
jeremy@chromium.orge8351b7e2009-02-10 22:25:39183
sammc4bcc4ed62016-10-27 10:13:59184DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
185 SendFdsClient,
186 SendFdsTestClientFixture) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35187 struct stat st;
188 int fd = open(kDevZeroPath, O_RDONLY);
189 fstat(fd, &st);
mark@chromium.orgd89eec82013-12-03 14:10:59190 EXPECT_GE(IGNORE_EINTR(close(fd)), 0);
sammc4bcc4ed62016-10-27 10:13:59191 SendFdsClientCommon("SendFdsClient", st.st_ino);
viettrungluu@chromium.org3c788582013-01-25 21:51:35192}
viettrungluu@chromium.org0cb7d8c82013-01-11 15:13:37193
Greg Thompsonbec327a72021-11-10 16:31:48194#if BUILDFLAG(IS_MAC)
viettrungluu@chromium.org3c788582013-01-25 21:51:35195// Test that FDs are correctly sent to a sandboxed process.
jeremy@chromium.orge8351b7e2009-02-10 22:25:39196// TODO(port): Make this test cross-platform.
viettrungluu@chromium.org3c788582013-01-25 21:51:35197TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
198 Init("SendFdsSandboxedClient");
199 RunServer();
200}
201
sammc4bcc4ed62016-10-27 10:13:59202DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
203 SendFdsSandboxedClient,
204 SendFdsTestClientFixture) {
jeremy@chromium.orge8351b7e2009-02-10 22:25:39205 struct stat st;
agl@chromium.org926394462009-02-11 23:23:12206 const int fd = open(kDevZeroPath, O_RDONLY);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39207 fstat(fd, &st);
sammc4bcc4ed62016-10-27 10:13:59208 ASSERT_LE(0, IGNORE_EINTR(close(fd)));
jeremy@chromium.orge8351b7e2009-02-10 22:25:39209
viettrungluu@chromium.org3c788582013-01-25 21:51:35210 // Enable the sandbox.
jeremy@chromium.orge8351b7e2009-02-10 22:25:39211 char* error_buff = NULL;
kerrneldf7ac7462016-09-24 00:39:26212 int error = sandbox::Seatbelt::Init(
213 sandbox::Seatbelt::kProfilePureComputation, SANDBOX_NAMED, &error_buff);
sammc4bcc4ed62016-10-27 10:13:59214 ASSERT_EQ(0, error);
215 ASSERT_FALSE(error_buff);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39216
kerrneldc059fe2016-04-12 16:39:06217 sandbox::Seatbelt::FreeError(error_buff);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39218
viettrungluu@chromium.org3c788582013-01-25 21:51:35219 // Make sure sandbox is really enabled.
sammc4bcc4ed62016-10-27 10:13:59220 ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY))
221 << "Sandbox wasn't properly enabled";
jeremy@chromium.orge8351b7e2009-02-10 22:25:39222
223 // See if we can receive a file descriptor.
sammc4bcc4ed62016-10-27 10:13:59224 SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39225}
Greg Thompsonbec327a72021-11-10 16:31:48226#endif // BUILDFLAG(IS_MAC)
jeremy@chromium.orge8351b7e2009-02-10 22:25:39227
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:22228} // namespace