[go: nahoru, domu]

blob: 5699e6d99f7649248b09c033cdc039c22562ee36 [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
5#include "build/build_config.h"
6
viettrungluu@chromium.org3c788582013-01-25 21:51:357#if defined(OS_POSIX)
jeremy@chromium.orge8351b7e2009-02-10 22:25:398#if defined(OS_MACOSX)
9extern "C" {
10#include <sandbox.h>
11}
12#endif
patrick@chromium.orgd67c2492009-03-20 17:26:0213#include <fcntl.h>
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5714#include <sys/stat.h>
viettrungluu@chromium.org3c788582013-01-25 21:51:3515#include <unistd.h>
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5716
erg@google.com7a4de7a62010-08-17 18:38:2417#include "base/file_descriptor_posix.h"
viettrungluu@chromium.org3c788582013-01-25 21:51:3518#include "base/message_loop.h"
19#include "base/pickle.h"
20#include "base/posix/eintr_wrapper.h"
21#include "ipc/ipc_message_utils.h"
22#include "ipc/ipc_test_base.h"
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5723
jeremy@chromium.orge8351b7e2009-02-10 22:25:3924namespace {
25
agl@chromium.org926394462009-02-11 23:23:1226const unsigned kNumFDsToSend = 20;
27const char* kDevZeroPath = "/dev/zero";
jeremy@chromium.orge8351b7e2009-02-10 22:25:3928
29static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
30 // Check that we can read from the FD.
31 char buf;
32 ssize_t amt_read = read(fd, &buf, 1);
33 ASSERT_EQ(amt_read, 1);
viettrungluu@chromium.org3c788582013-01-25 21:51:3534 ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
jeremy@chromium.orge8351b7e2009-02-10 22:25:3935
36 struct stat st;
37 ASSERT_EQ(fstat(fd, &st), 0);
38
39 ASSERT_EQ(close(fd), 0);
40
viettrungluu@chromium.org3c788582013-01-25 21:51:3541 // Compare inode numbers to check that the file sent over the wire is actually
42 // the one expected.
jeremy@chromium.orge8351b7e2009-02-10 22:25:3943 ASSERT_EQ(inode_num, st.st_ino);
44}
45
brettw@chromium.orgb7f59e822012-06-29 22:05:2646class MyChannelDescriptorListener : public IPC::Listener {
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5747 public:
viettrungluu@chromium.org3c788582013-01-25 21:51:3548 explicit MyChannelDescriptorListener(ino_t expected_inode_num)
agl@chromium.org926394462009-02-11 23:23:1249 : expected_inode_num_(expected_inode_num),
50 num_fds_received_(0) {}
jeremy@chromium.orge8351b7e2009-02-10 22:25:3951
jam@chromium.orga95986a2010-12-24 06:19:2852 virtual bool OnMessageReceived(const IPC::Message& message) {
jbates@chromium.orgce208f872012-03-07 20:42:5653 PickleIterator iter(message);
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5754
agl@chromium.org926394462009-02-11 23:23:1255 ++num_fds_received_;
agl@chromium.org5fe733de2009-02-11 18:59:2056 base::FileDescriptor descriptor;
jeremy@chromium.orge5a3ea32009-02-11 01:41:0257
viettrungluu@chromium.org3c788582013-01-25 21:51:3558 IPC::ParamTraits<base::FileDescriptor>::Read(&message, &iter, &descriptor);
jeremy@chromium.orge8351b7e2009-02-10 22:25:3959
60 VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
viettrungluu@chromium.org3c788582013-01-25 21:51:3561 if (num_fds_received_ == kNumFDsToSend)
agl@chromium.org926394462009-02-11 23:23:1262 MessageLoop::current()->Quit();
viettrungluu@chromium.org3c788582013-01-25 21:51:3563
jam@chromium.orga95986a2010-12-24 06:19:2864 return true;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5765 }
66
67 virtual void OnChannelError() {
68 MessageLoop::current()->Quit();
69 }
dmaclach@chromium.orgd484ab52010-12-09 01:12:2070
viettrungluu@chromium.org3c788582013-01-25 21:51:3571 bool GotExpectedNumberOfDescriptors() const {
72 return num_fds_received_ == kNumFDsToSend;
dmaclach@chromium.orgd484ab52010-12-09 01:12:2073 }
74
jeremy@chromium.orge8351b7e2009-02-10 22:25:3975 private:
76 ino_t expected_inode_num_;
agl@chromium.org926394462009-02-11 23:23:1277 unsigned num_fds_received_;
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5778};
79
viettrungluu@chromium.org3c788582013-01-25 21:51:3580class IPCSendFdsTest : public IPCTestBase {
81 protected:
82 void RunServer() {
83 // Set up IPC channel and start client.
84 MyChannelDescriptorListener listener(-1);
85 CreateChannel(&listener);
86 ASSERT_TRUE(ConnectChannel());
87 ASSERT_TRUE(StartClient());
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5788
viettrungluu@chromium.org3c788582013-01-25 21:51:3589 for (unsigned i = 0; i < kNumFDsToSend; ++i) {
90 const int fd = open(kDevZeroPath, O_RDONLY);
91 ASSERT_GE(fd, 0);
92 base::FileDescriptor descriptor(fd, true);
jeremy@chromium.orgc2f10ed2009-02-10 00:52:5793
viettrungluu@chromium.org3c788582013-01-25 21:51:3594 IPC::Message* message =
95 new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
96 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
97 ASSERT_TRUE(sender()->Send(message));
98 }
99
100 // Run message loop.
101 MessageLoop::current()->Run();
102
103 // Close the channel so the client's OnChannelError() gets fired.
104 channel()->Close();
105
106 EXPECT_TRUE(WaitForClientShutdown());
107 DestroyChannel();
agl@chromium.org926394462009-02-11 23:23:12108 }
viettrungluu@chromium.org3c788582013-01-25 21:51:35109};
110
111TEST_F(IPCSendFdsTest, DescriptorTest) {
112 Init("SendFdsClient");
113 RunServer();
114}
115
116int SendFdsClientCommon(const std::string& test_client_name,
117 ino_t expected_inode_num) {
118 MessageLoopForIO main_message_loop;
119 MyChannelDescriptorListener listener(expected_inode_num);
120
121 // Set up IPC channel.
122 IPC::Channel channel(IPCTestBase::GetChannelName(test_client_name),
123 IPC::Channel::MODE_CLIENT,
124 &listener);
125 CHECK(channel.Connect());
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57126
127 // Run message loop.
128 MessageLoop::current()->Run();
129
viettrungluu@chromium.org3c788582013-01-25 21:51:35130 // Verify that the message loop was exited due to getting the correct number
131 // of descriptors, and not because of the channel closing unexpectedly.
dmaclach@chromium.orgd484ab52010-12-09 01:12:20132 CHECK(listener.GotExpectedNumberOfDescriptors());
133
jeremy@chromium.orge8351b7e2009-02-10 22:25:39134 return 0;
135}
136
viettrungluu@chromium.org3c788582013-01-25 21:51:35137MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsClient) {
138 struct stat st;
139 int fd = open(kDevZeroPath, O_RDONLY);
140 fstat(fd, &st);
141 EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
142 return SendFdsClientCommon("SendFdsClient", st.st_ino);
143}
viettrungluu@chromium.org0cb7d8c82013-01-11 15:13:37144
jeremy@chromium.orge8351b7e2009-02-10 22:25:39145#if defined(OS_MACOSX)
viettrungluu@chromium.org3c788582013-01-25 21:51:35146// Test that FDs are correctly sent to a sandboxed process.
jeremy@chromium.orge8351b7e2009-02-10 22:25:39147// TODO(port): Make this test cross-platform.
viettrungluu@chromium.org3c788582013-01-25 21:51:35148TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
149 Init("SendFdsSandboxedClient");
150 RunServer();
151}
152
153MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) {
jeremy@chromium.orge8351b7e2009-02-10 22:25:39154 struct stat st;
agl@chromium.org926394462009-02-11 23:23:12155 const int fd = open(kDevZeroPath, O_RDONLY);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39156 fstat(fd, &st);
viettrungluu@chromium.org3c788582013-01-25 21:51:35157 if (HANDLE_EINTR(close(fd)) < 0)
thakis@chromium.org34f40942010-10-04 00:34:04158 return -1;
jeremy@chromium.orge8351b7e2009-02-10 22:25:39159
viettrungluu@chromium.org3c788582013-01-25 21:51:35160 // Enable the sandbox.
jeremy@chromium.orge8351b7e2009-02-10 22:25:39161 char* error_buff = NULL;
162 int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
163 &error_buff);
164 bool success = (error == 0 && error_buff == NULL);
viettrungluu@chromium.org3c788582013-01-25 21:51:35165 if (!success)
jeremy@chromium.orge8351b7e2009-02-10 22:25:39166 return -1;
jeremy@chromium.orge8351b7e2009-02-10 22:25:39167
168 sandbox_free_error(error_buff);
169
viettrungluu@chromium.org3c788582013-01-25 21:51:35170 // Make sure sandbox is really enabled.
agl@chromium.org926394462009-02-11 23:23:12171 if (open(kDevZeroPath, O_RDONLY) != -1) {
jeremy@chromium.orge8351b7e2009-02-10 22:25:39172 LOG(ERROR) << "Sandbox wasn't properly enabled";
173 return -1;
174 }
175
176 // See if we can receive a file descriptor.
viettrungluu@chromium.org3c788582013-01-25 21:51:35177 return SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
jeremy@chromium.orge8351b7e2009-02-10 22:25:39178}
179#endif // defined(OS_MACOSX)
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57180
viettrungluu@chromium.org2a3aa7b52013-01-11 20:56:22181} // namespace
182
jeremy@chromium.orgc2f10ed2009-02-10 00:52:57183#endif // defined(OS_POSIX)