blob: 267daf0c27af2bd2518121b1cf7fe3ed0f6e0773 [file] [log] [blame]
Avi Drissmanea1be232022-09-14 23:29:061// Copyright 2012 The Chromium Authors
[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
Xiaohan Wang0ecc876d2022-01-07 19:57:155#include "build/build_config.h"
[email protected]c2f10ed2009-02-10 00:52:576
Greg Thompsonbec327a72021-11-10 16:31:487#if BUILDFLAG(IS_MAC)
[email protected]e8351b7e2009-02-10 22:25:398extern "C" {
9#include <sandbox.h>
Nico Webere86ed9b32019-02-22 18:11:1210}
[email protected]e8351b7e2009-02-10 22:25:3911#endif
Greg Thompsonbec327a72021-11-10 16:31:4812
[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
[email protected]7a4de7a62010-08-17 18:38:2422#include "base/file_descriptor_posix.h"
[email protected]3c788582013-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"
[email protected]dc875dc2013-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"
[email protected]3c788582013-01-25 21:51:3530#include "ipc/ipc_message_utils.h"
31#include "ipc/ipc_test_base.h"
[email protected]c2f10ed2009-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
[email protected]e8351b7e2009-02-10 22:25:3940namespace {
41
yusukesc986c5432015-05-06 19:45:4542const unsigned kNumFDsToSend = 7; // per message
43const unsigned kNumMessages = 20;
[email protected]926394462009-02-11 23:23:1244const char* kDevZeroPath = "/dev/zero";
[email protected]e8351b7e2009-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
[email protected]dc875dc2013-10-15 00:07:0050class MyChannelDescriptorListenerBase : public IPC::Listener {
[email protected]c2f10ed2009-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);
[email protected]5fe733de2009-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 }
[email protected]a95986a82010-12-24 06:19:2859 return true;
[email protected]c2f10ed2009-02-10 00:52:5760 }
61
[email protected]dc875dc2013-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) {
[email protected]6b47b4d2013-10-10 21:12:1472 }
73
sammc6ed3efb2016-11-23 03:17:3574 unsigned num_fds_received() const {
75 return num_fds_received_;
[email protected]6b47b4d2013-10-10 21:12:1476 }
Helmut Januschka448ebd72024-01-09 00:47:4677 void Run() { loop_.Run(); }
78 void OnChannelError() override { loop_.QuitWhenIdle(); }
[email protected]dc875dc2013-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);
[email protected]dc875dc2013-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 }
[email protected]dc875dc2013-10-15 00:07:00102 }
103
[email protected]e8351b7e2009-02-10 22:25:39104 private:
105 ino_t expected_inode_num_;
[email protected]926394462009-02-11 23:23:12106 unsigned num_fds_received_;
Helmut Januschka448ebd72024-01-09 00:47:46107 base::RunLoop loop_;
[email protected]c2f10ed2009-02-10 00:52:57108};
109
sammc4bcc4ed62016-10-27 10:13:59110class IPCSendFdsTest : public IPCChannelMojoTestBase {
[email protected]3c788582013-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
[email protected]3c788582013-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());
[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.
Helmut Januschka448ebd72024-01-09 00:47:46137 listener.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 }
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
[email protected]3c788582013-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) {
[email protected]3c788582013-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);
[email protected]3c788582013-01-25 21:51:35168
sammc4bcc4ed62016-10-27 10:13:59169 // Set up IPC channel.
170 Connect(&listener);
[email protected]c2f10ed2009-02-10 00:52:57171
sammc4bcc4ed62016-10-27 10:13:59172 // Run message loop.
Helmut Januschka448ebd72024-01-09 00:47:46173 listener.Run();
[email protected]c2f10ed2009-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());
[email protected]d484ab52010-12-09 01:12:20178
sammc4bcc4ed62016-10-27 10:13:59179 Close();
180 }
181};
[email protected]e8351b7e2009-02-10 22:25:39182
sammc4bcc4ed62016-10-27 10:13:59183DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE(
184 SendFdsClient,
185 SendFdsTestClientFixture) {
[email protected]3c788582013-01-25 21:51:35186 struct stat st;
187 int fd = open(kDevZeroPath, O_RDONLY);
188 fstat(fd, &st);
[email protected]d89eec82013-12-03 14:10:59189 EXPECT_GE(IGNORE_EINTR(close(fd)), 0);
sammc4bcc4ed62016-10-27 10:13:59190 SendFdsClientCommon("SendFdsClient", st.st_ino);
[email protected]3c788582013-01-25 21:51:35191}
[email protected]0cb7d8c82013-01-11 15:13:37192
Greg Thompsonbec327a72021-11-10 16:31:48193#if BUILDFLAG(IS_MAC)
[email protected]3c788582013-01-25 21:51:35194// Test that FDs are correctly sent to a sandboxed process.
[email protected]e8351b7e2009-02-10 22:25:39195// TODO(port): Make this test cross-platform.
[email protected]3c788582013-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) {
[email protected]e8351b7e2009-02-10 22:25:39204 struct stat st;
[email protected]926394462009-02-11 23:23:12205 const int fd = open(kDevZeroPath, O_RDONLY);
[email protected]e8351b7e2009-02-10 22:25:39206 fstat(fd, &st);
sammc4bcc4ed62016-10-27 10:13:59207 ASSERT_LE(0, IGNORE_EINTR(close(fd)));
[email protected]e8351b7e2009-02-10 22:25:39208
[email protected]3c788582013-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;
[email protected]e8351b7e2009-02-10 22:25:39214
[email protected]3c788582013-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";
[email protected]e8351b7e2009-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);
[email protected]e8351b7e2009-02-10 22:25:39221}
Greg Thompsonbec327a72021-11-10 16:31:48222#endif // BUILDFLAG(IS_MAC)
[email protected]e8351b7e2009-02-10 22:25:39223
[email protected]2a3aa7b52013-01-11 20:56:22224} // namespace