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) |