Chromium Code Reviews| Index: chrome/common/ipc_send_fds_test.cc |
| diff --git a/chrome/common/ipc_send_fds_test.cc b/chrome/common/ipc_send_fds_test.cc |
| index 2c31f01a896763497fd0cab7053766896bed74f3..d0ef834d6f023abae8a7d920e5540894931b53db 100644 |
| --- a/chrome/common/ipc_send_fds_test.cc |
| +++ b/chrome/common/ipc_send_fds_test.cc |
| @@ -6,6 +6,11 @@ |
| #include "chrome/common/ipc_tests.h" |
| +#if defined(OS_MACOSX) |
| +extern "C" { |
| +#include <sandbox.h> |
| +} |
| +#endif |
| #include <sys/stat.h> |
| #include "base/message_loop.h" |
| @@ -14,8 +19,28 @@ |
| #if defined(OS_POSIX) |
| +namespace { |
| + |
| +const char* kDevRandomPath = "/dev/random"; |
| + |
| +static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) { |
|
John Grabowski
2009/02/10 20:54:29
Perhaps a comment explaining why we need to compar
|
| + // Check that we can read from the FD. |
| + char buf; |
| + ssize_t amt_read = read(fd, &buf, 1); |
| + ASSERT_EQ(amt_read, 1); |
| + |
| + struct stat st; |
| + ASSERT_EQ(fstat(fd, &st), 0); |
| + |
| + ASSERT_EQ(close(fd), 0); |
| + ASSERT_EQ(inode_num, st.st_ino); |
| +} |
| + |
| class MyChannelDescriptorListener : public IPC::Channel::Listener { |
| public: |
| + MyChannelDescriptorListener(ino_t expected_inode_num) |
| + : expected_inode_num_(expected_inode_num) {} |
| + |
| virtual void OnMessageReceived(const IPC::Message& message) { |
| void* iter = NULL; |
| @@ -23,40 +48,24 @@ class MyChannelDescriptorListener : public IPC::Channel::Listener { |
| ASSERT_TRUE( |
| IPC::ParamTraits<FileDescriptor>::Read(&message, &iter, &descriptor)); |
| - VerifyDescriptor(&descriptor); |
| + |
| + VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_); |
| MessageLoop::current()->Quit(); |
| } |
| virtual void OnChannelError() { |
| MessageLoop::current()->Quit(); |
| } |
| - |
| -private: |
| - static void VerifyDescriptor(FileDescriptor* descriptor) { |
| - const int fd = open("/dev/null", O_RDONLY); |
| - struct stat st1, st2; |
| - fstat(fd, &st1); |
| - close(fd); |
| - fstat(descriptor->fd, &st2); |
| - close(descriptor->fd); |
| - ASSERT_EQ(st1.st_ino, st2.st_ino); |
| - } |
| + private: |
| + ino_t expected_inode_num_; |
| }; |
| -TEST_F(IPCChannelTest, DescriptorTest) { |
| - // Setup IPC channel. |
| - MyChannelDescriptorListener listener; |
| - |
| - IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
| - &listener); |
| - chan.Connect(); |
| - |
| - base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT, |
| - &chan); |
| +void TestDescriptorServer(IPC::Channel &chan, |
| + base::ProcessHandle process_handle) { |
| ASSERT_TRUE(process_handle); |
| FileDescriptor descriptor; |
| - const int fd = open("/dev/null", O_RDONLY); |
| + const int fd = open(kDevRandomPath, O_RDONLY); |
| ASSERT_GE(fd, 0); |
| descriptor.auto_close = true; |
| descriptor.fd = fd; |
| @@ -77,19 +86,86 @@ TEST_F(IPCChannelTest, DescriptorTest) { |
| EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000)); |
| } |
| -MULTIPROCESS_TEST_MAIN(RunTestDescriptorClient) { |
| +int TestDescriptorClient(ino_t expected_inode_num) { |
| MessageLoopForIO main_message_loop; |
| - MyChannelDescriptorListener listener; |
| + MyChannelDescriptorListener listener(expected_inode_num); |
| - // setup IPC channel |
| + // Setup IPC channel. |
| IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, |
| &listener); |
| chan.Connect(); |
| - |
| - // run message loop |
| MessageLoop::current()->Run(); |
| - // return true; |
| - return NULL; |
| + |
| + return 0; |
| +} |
| + |
| +} // namespace |
| + |
| +// --------------------------------------------------------------------------- |
| +#if defined(OS_MACOSX) |
| +// TODO(port): Make this test cross-platform. |
| +MULTIPROCESS_TEST_MAIN(RunTestDescriptorClientSandboxed) { |
| + struct stat st; |
| + const int fd = open(kDevRandomPath, O_RDONLY); |
| + fstat(fd, &st); |
| + close(fd); |
| + |
| + // Enable the Sandbox. |
| + char* error_buff = NULL; |
| + int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, |
| + &error_buff); |
| + bool success = (error == 0 && error_buff == NULL); |
| + if (!success) { |
| + return -1; |
| + } |
| + |
| + sandbox_free_error(error_buff); |
| + |
| + // Make sure Sandbox is really enabled. |
| + if (open(kDevRandomPath, O_RDONLY) != -1) { |
| + LOG(ERROR) << "Sandbox wasn't properly enabled"; |
| + return -1; |
| + } |
| + |
| + // See if we can receive a file descriptor. |
| + return TestDescriptorClient(st.st_ino); |
| +} |
| + |
| +TEST_F(IPCChannelTest, DescriptorTestSandboxed) { |
| + // Setup IPC channel. |
| + MyChannelDescriptorListener listener(-1); |
| + |
| + IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
| + &listener); |
| + chan.Connect(); |
| + |
| + base::ProcessHandle process_handle = SpawnChild( |
| + TEST_DESCRIPTOR_CLIENT_SANDBOXED, |
| + &chan); |
| + TestDescriptorServer(chan, process_handle); |
| +} |
| +#endif // defined(OS_MACOSX) |
| + |
| +MULTIPROCESS_TEST_MAIN(RunTestDescriptorClient) { |
| + struct stat st; |
| + const int fd = open(kDevRandomPath, O_RDONLY); |
| + fstat(fd, &st); |
| + close(fd); |
| + |
| + return TestDescriptorClient(st.st_ino); |
| +} |
| + |
| +TEST_F(IPCChannelTest, DescriptorTest) { |
| + // Setup IPC channel. |
| + MyChannelDescriptorListener listener(-1); |
| + |
| + IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
| + &listener); |
| + chan.Connect(); |
| + |
| + base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT, |
| + &chan); |
| + TestDescriptorServer(chan, process_handle); |
| } |
| #endif // defined(OS_POSIX) |