[go: nahoru, domu]

blob: 267daf0c27af2bd2518121b1cf7fe3ed0f6e0773 [file] [log] [blame]
Avi Drissmanea1be232022-09-14 23:29:061// Copyright 2012 The Chromium Authors
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
Xiaohan Wang0ecc8762022-01-07 19:57:155#include "build/build_config.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"
morrita4b5c28e22015-01-14 21:17:0629#include "ipc/ipc_message_attachment_set.h"
viettrungluu@chromium.org3c788582013-01-25 21:51:3530#include "ipc/ipc_message_utils.h"
31#include "ipc/ipc_test_base.h"
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5732
Greg Thompsonbec327a72021-11-10 16:31:4833#if BUILDFLAG(IS_MAC)
kerrneldc059fe2016-04-12 16:39:0634#include "sandbox/mac/seatbelt.h"
Greg Thompson9360c5d42021-12-01 17:55:3435#elif BUILDFLAG(IS_FUCHSIA)
36#include "base/memory/scoped_refptr.h"
37#include "base/test/scoped_dev_zero_fuchsia.h"
kerrneldc059fe2016-04-12 16:39:0638#endif
39
jeremy@chromium.orge8351b7e2009-02-10 22:25:3940namespace {
41
yusukesc986c5432015-05-06 19:45:4542const unsigned kNumFDsToSend = 7; // per message
43const unsigned kNumMessages = 20;
agl@chromium.org926394462009-02-11 23:23:1244const char* kDevZeroPath = "/dev/zero";
jeremy@chromium.orge8351b7e2009-02-10 22:25:3945
anujk.sharma5a7ffe2f2015-01-22 05:39:3746static_assert(kNumFDsToSend ==
47 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage,
48 "The number of FDs to send must be kMaxDescriptorsPerMessage.");
yusukesd0329fc2015-01-06 06:56:3449
hubbe@chromium.orgdc875dc2013-10-15 00:07:0050class MyChannelDescriptorListenerBase : public IPC::Listener {
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5751 public:
dchengfe61fca2014-10-22 02:29:5252 bool OnMessageReceived(const IPC::Message& message) override {
brettwbd4d7112015-06-03 04:29:2553 base::PickleIterator iter(message);
agl@chromium.org5fe733de2009-02-11 18:59:2054 base::FileDescriptor descriptor;
yusukesd0329fc2015-01-06 06:56:3455 while (IPC::ParamTraits<base::FileDescriptor>::Read(
56 &message, &iter, &descriptor)) {
57 HandleFD(descriptor.fd);
58 }
jam@chromium.orga95986a2010-12-24 06:19:2859 return true;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5760 }
61
hubbe@chromium.orgdc875dc2013-10-15 00:07:0062 protected:
63 virtual void HandleFD(int fd) = 0;
64};
65
66class MyChannelDescriptorListener : public MyChannelDescriptorListenerBase {
67 public:
68 explicit MyChannelDescriptorListener(ino_t expected_inode_num)
69 : MyChannelDescriptorListenerBase(),
70 expected_inode_num_(expected_inode_num),
71 num_fds_received_(0) {
hubbe@chromium.org6b47b4d2013-10-10 21:12:1472 }
73
sammc6ed3efb2016-11-23 03:17:3574 unsigned num_fds_received() const {
75 return num_fds_received_;
hubbe@chromium.org6b47b4d2013-10-10 21:12:1476 }
Helmut Januschka448ebd72024-01-09 00:47:4677 void Run() { loop_.Run(); }
78 void OnChannelError() override { loop_.QuitWhenIdle(); }
hubbe@chromium.orgdc875dc2013-10-15 00:07:0079
80 protected:
dchengfe61fca2014-10-22 02:29:5281 void HandleFD(int fd) override {
yusukesd0329fc2015-01-06 06:56:3482 ASSERT_GE(fd, 0);
hubbe@chromium.orgdc875dc2013-10-15 00:07:0083 // Check that we can read from the FD.
84 char buf;
85 ssize_t amt_read = read(fd, &buf, 1);
86 ASSERT_EQ(amt_read, 1);
87 ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
88
89 struct stat st;
90 ASSERT_EQ(fstat(fd, &st), 0);
91
92 ASSERT_EQ(close(fd), 0);
93
94 // Compare inode numbers to check that the file sent over the wire is
95 // actually the one expected.
96 ASSERT_EQ(expected_inode_num_, st.st_ino);
97
98 ++num_fds_received_;
Helmut Januschka448ebd72024-01-09 00:47:4699 if (num_fds_received_ == kNumFDsToSend * kNumMessages) {
100 loop_.QuitWhenIdle();
101 }
hubbe@chromium.orgdc875dc2013-10-15 00:07:00102 }
103
jeremy@chromium.orge8351b7e2009-02-10 22:25:39104 private:
105 ino_t expected_inode_num_;
agl@chromium.org926394462009-02-11 23:23:12106 unsigned num_fds_received_;
Helmut Januschka448ebd72024-01-09 00:47:46107 base::RunLoop loop_;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57108};
109
sammc4bcc4ed62016-10-27 10:13:59110class IPCSendFdsTest : public IPCChannelMojoTestBase {
viettrungluu@chromium.org3c788582013-01-25 21:51:35111 protected:
Greg Thompson9360c5d42021-12-01 17:55:34112 void SetUp() override {
113#if BUILDFLAG(IS_FUCHSIA)
114 ASSERT_TRUE(dev_zero_);
115#endif
116 }
117
viettrungluu@chromium.org3c788582013-01-25 21:51:35118 void RunServer() {
119 // Set up IPC channel and start client.
120 MyChannelDescriptorListener listener(-1);
121 CreateChannel(&listener);
122 ASSERT_TRUE(ConnectChannel());
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57123
yusukesd0329fc2015-01-06 06:56:34124 for (unsigned i = 0; i < kNumMessages; ++i) {
bbudge@chromium.org753bb252013-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 }
viettrungluu@chromium.org3c788582013-01-25 21:51:35133 ASSERT_TRUE(sender()->Send(message));
134 }
135
136 // Run message loop.
Helmut Januschka448ebd72024-01-09 00:47:46137 listener.Run();
viettrungluu@chromium.org3c788582013-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();
agl@chromium.org926394462009-02-11 23:23:12144 }
Greg Thompson9360c5d42021-12-01 17:55:34145
146 private:
147#if BUILDFLAG(IS_FUCHSIA)
148 scoped_refptr<base::ScopedDevZero> dev_zero_ = base::ScopedDevZero::Get();
149#endif
viettrungluu@chromium.org3c788582013-01-25 21:51:35150};
151
Greg Thompson9360c5d42021-12-01 17:55:34152// Disabled on Fuchsia due to failures; see https://crbug.com/1272424.
153#if BUILDFLAG(IS_FUCHSIA)
154#define MAYBE_DescriptorTest DISABLED_DescriptorTest
155#else
156#define MAYBE_DescriptorTest DescriptorTest
157#endif
158TEST_F(IPCSendFdsTest, MAYBE_DescriptorTest) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35159 Init("SendFdsClient");
160 RunServer();
161}
162
sammc4bcc4ed62016-10-27 10:13:59163class SendFdsTestClientFixture : public IpcChannelMojoTestClient {
164 protected:
165 void SendFdsClientCommon(const std::string& test_client_name,
166 ino_t expected_inode_num) {
167 MyChannelDescriptorListener listener(expected_inode_num);
viettrungluu@chromium.org3c788582013-01-25 21:51:35168
sammc4bcc4ed62016-10-27 10:13:59169 // Set up IPC channel.
170 Connect(&listener);
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57171
sammc4bcc4ed62016-10-27 10:13:59172 // Run message loop.
Helmut Januschka448ebd72024-01-09 00:47:46173 listener.Run();
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57174
sammc4bcc4ed62016-10-27 10:13:59175 // Verify that the message loop was exited due to getting the correct number
176 // of descriptors, and not because of the channel closing unexpectedly.
sammc6ed3efb2016-11-23 03:17:35177 EXPECT_EQ(kNumFDsToSend * kNumMessages, listener.num_fds_received());
dmaclach@chromium.orgd484ab52010-12-09 01:12:20178
sammc4bcc4ed62016-10-27 10:13:59179 Close();
180 }
181};
jeremy@chromium.orge8351b7e2009-02-10 22:25:39182
sammc4bcc4ed62016-10-27 10:13:59183DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
184 SendFdsClient,
185 SendFdsTestClientFixture) {
viettrungluu@chromium.org3c788582013-01-25 21:51:35186 struct stat st;
187 int fd = open(kDevZeroPath, O_RDONLY);
188 fstat(fd, &st);
mark@chromium.orgd89eec82013-12-03 14:10:59189 EXPECT_GE(IGNORE_EINTR(close(fd)), 0);
sammc4bcc4ed62016-10-27 10:13:59190 SendFdsClientCommon("SendFdsClient", st.st_ino);
viettrungluu@chromium.org3c788582013-01-25 21:51:35191}
viettrungluu@chromium.org0cb7d8c82013-01-11 15:13:37192
Greg Thompsonbec327a72021-11-10 16:31:48193#if BUILDFLAG(IS_MAC)
viettrungluu@chromium.org3c788582013-01-25 21:51:35194// Test that FDs are correctly sent to a sandboxed process.
jeremy@chromium.orge8351b7e2009-02-10 22:25:39195// TODO(port): Make this test cross-platform.
viettrungluu@chromium.org3c788582013-01-25 21:51:35196TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
197 Init("SendFdsSandboxedClient");
198 RunServer();
199}
200
sammc4bcc4ed62016-10-27 10:13:59201DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
202 SendFdsSandboxedClient,
203 SendFdsTestClientFixture) {
jeremy@chromium.orge8351b7e2009-02-10 22:25:39204 struct stat st;
agl@chromium.org926394462009-02-11 23:23:12205 const int fd = open(kDevZeroPath, O_RDONLY);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39206 fstat(fd, &st);
sammc4bcc4ed62016-10-27 10:13:59207 ASSERT_LE(0, IGNORE_EINTR(close(fd)));
jeremy@chromium.orge8351b7e2009-02-10 22:25:39208
viettrungluu@chromium.org3c788582013-01-25 21:51:35209 // Enable the sandbox.
Robert Seseka4faabc2022-12-01 18:19:58210 std::string error;
211 ASSERT_TRUE(sandbox::Seatbelt::Init(
212 sandbox::Seatbelt::kProfilePureComputation, SANDBOX_NAMED, &error))
213 << error;
jeremy@chromium.orge8351b7e2009-02-10 22:25:39214
viettrungluu@chromium.org3c788582013-01-25 21:51:35215 // Make sure sandbox is really enabled.
sammc4bcc4ed62016-10-27 10:13:59216 ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY))
217 << "Sandbox wasn't properly enabled";
jeremy@chromium.orge8351b7e2009-02-10 22:25:39218
219 // See if we can receive a file descriptor.
sammc4bcc4ed62016-10-27 10:13:59220 SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39221}
Greg Thompsonbec327a72021-11-10 16:31:48222#endif // BUILDFLAG(IS_MAC)
jeremy@chromium.orge8351b7e2009-02-10 22:25:39223
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:22224} // namespace