Skip to content

Commit

Permalink
Add test to check that FDs are sent through the OS X Sandbox ok.
Browse files Browse the repository at this point in the history
Review URL: http://codereview.chromium.org/21223

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9519 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
jeremy@chromium.org committed Feb 10, 2009
1 parent 901ece8 commit bd267a7
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 30 deletions.
2 changes: 2 additions & 0 deletions chrome/chrome.xcodeproj/project.pbxproj
Expand Up @@ -2421,6 +2421,7 @@
B5D16EF40F2145C600861FAC /* url_fixer_upper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fixer_upper.cc; sourceTree = "<group>"; }; B5D16EF40F2145C600861FAC /* url_fixer_upper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fixer_upper.cc; sourceTree = "<group>"; };
B5D16EF50F2145C600861FAC /* url_fixer_upper_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fixer_upper_unittest.cc; sourceTree = "<group>"; }; B5D16EF50F2145C600861FAC /* url_fixer_upper_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = url_fixer_upper_unittest.cc; sourceTree = "<group>"; };
B5D7CD350EF0702F00EE645F /* ipc_channel_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipc_channel_posix.h; sourceTree = "<group>"; }; B5D7CD350EF0702F00EE645F /* ipc_channel_posix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipc_channel_posix.h; sourceTree = "<group>"; };
B5EEB5E00F42044300CD3A28 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = System/Library/Frameworks/System.framework; sourceTree = SDKROOT; };
B5FDBFAE0EE4623000BEC6E6 /* ipc_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ipc_tests; sourceTree = BUILT_PRODUCTS_DIR; }; B5FDBFAE0EE4623000BEC6E6 /* ipc_tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ipc_tests; sourceTree = BUILT_PRODUCTS_DIR; };
B5FDC0570EE488E500BEC6E6 /* ipc_channel_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ipc_channel_posix.cc; sourceTree = "<group>"; }; B5FDC0570EE488E500BEC6E6 /* ipc_channel_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ipc_channel_posix.cc; sourceTree = "<group>"; };
B6CCB9CE0F1EC32700106F0D /* constrained_window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constrained_window.h; path = tab_contents/constrained_window.h; sourceTree = "<group>"; }; B6CCB9CE0F1EC32700106F0D /* constrained_window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = constrained_window.h; path = tab_contents/constrained_window.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2974,6 +2975,7 @@
56E1D7DF17D327BFCB0B895D /* test_web_contents.cc */, 56E1D7DF17D327BFCB0B895D /* test_web_contents.cc */,
699499C4FBA07FB2D7B298A2 /* user_script.cc */, 699499C4FBA07FB2D7B298A2 /* user_script.cc */,
37521A11B07C479E93A39D52 /* user_script_unittest.cc */, 37521A11B07C479E93A39D52 /* user_script_unittest.cc */,
B5EEB5E00F42044300CD3A28 /* System.framework */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
Expand Down
140 changes: 110 additions & 30 deletions chrome/common/ipc_send_fds_test.cc
Expand Up @@ -6,6 +6,11 @@


#include "chrome/common/ipc_tests.h" #include "chrome/common/ipc_tests.h"


#if defined(OS_MACOSX)
extern "C" {
#include <sandbox.h>
}
#endif
#include <sys/stat.h> #include <sys/stat.h>


#include "base/message_loop.h" #include "base/message_loop.h"
Expand All @@ -14,49 +19,56 @@


#if defined(OS_POSIX) #if defined(OS_POSIX)


namespace {

const char* kDevRandomPath = "/dev/random";

static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
// 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);

// We compare iNode numbers to check that the file sent over the wire
// was actually the same physical file as the one we were expecting.
ASSERT_EQ(inode_num, st.st_ino);
}

class MyChannelDescriptorListener : public IPC::Channel::Listener { class MyChannelDescriptorListener : public IPC::Channel::Listener {
public: public:
MyChannelDescriptorListener(ino_t expected_inode_num)
: expected_inode_num_(expected_inode_num) {}

virtual void OnMessageReceived(const IPC::Message& message) { virtual void OnMessageReceived(const IPC::Message& message) {
void* iter = NULL; void* iter = NULL;


FileDescriptor descriptor; FileDescriptor descriptor;


ASSERT_TRUE( ASSERT_TRUE(
IPC::ParamTraits<FileDescriptor>::Read(&message, &iter, &descriptor)); IPC::ParamTraits<FileDescriptor>::Read(&message, &iter, &descriptor));
VerifyDescriptor(&descriptor);
VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
MessageLoop::current()->Quit(); MessageLoop::current()->Quit();
} }


virtual void OnChannelError() { virtual void OnChannelError() {
MessageLoop::current()->Quit(); MessageLoop::current()->Quit();
} }

private:
private: ino_t expected_inode_num_;
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);
}
}; };


TEST_F(IPCChannelTest, DescriptorTest) { void TestDescriptorServer(IPC::Channel &chan,
// Setup IPC channel. base::ProcessHandle process_handle) {
MyChannelDescriptorListener listener;

IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
&listener);
chan.Connect();

base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT,
&chan);
ASSERT_TRUE(process_handle); ASSERT_TRUE(process_handle);


FileDescriptor descriptor; FileDescriptor descriptor;
const int fd = open("/dev/null", O_RDONLY); const int fd = open(kDevRandomPath, O_RDONLY);
ASSERT_GE(fd, 0); ASSERT_GE(fd, 0);
descriptor.auto_close = true; descriptor.auto_close = true;
descriptor.fd = fd; descriptor.fd = fd;
Expand All @@ -77,19 +89,87 @@ TEST_F(IPCChannelTest, DescriptorTest) {
EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000)); EXPECT_TRUE(base::WaitForSingleProcess(process_handle, 5000));
} }


MULTIPROCESS_TEST_MAIN(RunTestDescriptorClient) { int TestDescriptorClient(ino_t expected_inode_num) {
MessageLoopForIO main_message_loop; 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, IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
&listener); &listener);
chan.Connect(); chan.Connect();

// run message loop
MessageLoop::current()->Run(); 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 that FDs are correctly sent to a sandboxed process.
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) #endif // defined(OS_POSIX)
6 changes: 6 additions & 0 deletions chrome/common/ipc_tests.cc
Expand Up @@ -110,6 +110,12 @@ base::ProcessHandle IPCChannelTest::SpawnChild(ChildType child_type,
debug_on_start); debug_on_start);
channel->OnClientConnected(); channel->OnClientConnected();
break; break;
case TEST_DESCRIPTOR_CLIENT_SANDBOXED:
ret = MultiProcessTest::SpawnChild(L"RunTestDescriptorClientSandboxed",
fds_to_map,
debug_on_start);
channel->OnClientConnected();
break;
case TEST_REFLECTOR: case TEST_REFLECTOR:
ret = MultiProcessTest::SpawnChild(L"RunReflector", ret = MultiProcessTest::SpawnChild(L"RunReflector",
fds_to_map, fds_to_map,
Expand Down
1 change: 1 addition & 0 deletions chrome/common/ipc_tests.h
Expand Up @@ -13,6 +13,7 @@
enum ChildType { enum ChildType {
TEST_CLIENT, TEST_CLIENT,
TEST_DESCRIPTOR_CLIENT, TEST_DESCRIPTOR_CLIENT,
TEST_DESCRIPTOR_CLIENT_SANDBOXED,
TEST_REFLECTOR, TEST_REFLECTOR,
FUZZER_SERVER FUZZER_SERVER
}; };
Expand Down

0 comments on commit bd267a7

Please sign in to comment.