summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormdempsky@chromium.org <mdempsky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-11 00:44:13 +0000
committermdempsky@chromium.org <mdempsky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-11 00:44:13 +0000
commit3cb62e837a26f09a64732105171ccbc7a7ca9f50 (patch)
tree70447b5876a2312eb5424c90c30b2332d0b428bf
parent07283f73e209e11aacdc2c0c6a6ffe80eb5e0e3a (diff)
downloadchromium_src-3cb62e837a26f09a64732105171ccbc7a7ca9f50.zip
chromium_src-3cb62e837a26f09a64732105171ccbc7a7ca9f50.tar.gz
chromium_src-3cb62e837a26f09a64732105171ccbc7a7ca9f50.tar.bz2
Add unit test to check for broker FD leak
BUG=360274 Review URL: https://codereview.chromium.org/229893002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@263147 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--sandbox/linux/services/broker_process.h2
-rw-r--r--sandbox/linux/services/broker_process_unittest.cc59
-rw-r--r--sandbox/linux/tests/unit_tests.cc11
-rw-r--r--sandbox/linux/tests/unit_tests.h13
-rw-r--r--sandbox/linux/tests/unit_tests_unittest.cc5
5 files changed, 90 insertions, 0 deletions
diff --git a/sandbox/linux/services/broker_process.h b/sandbox/linux/services/broker_process.h
index b312b8f6..6645deb 100644
--- a/sandbox/linux/services/broker_process.h
+++ b/sandbox/linux/services/broker_process.h
@@ -97,6 +97,8 @@ class SANDBOX_EXPORT BrokerProcess {
const std::vector<std::string> allowed_w_files_; // Files allowed for write.
int ipc_socketpair_; // Our communication channel to parent or child.
DISALLOW_IMPLICIT_CONSTRUCTORS(BrokerProcess);
+
+ friend class BrokerProcessTestHelper;
};
} // namespace sandbox
diff --git a/sandbox/linux/services/broker_process_unittest.cc b/sandbox/linux/services/broker_process_unittest.cc
index 7f1a685..dfc149e 100644
--- a/sandbox/linux/services/broker_process_unittest.cc
+++ b/sandbox/linux/services/broker_process_unittest.cc
@@ -11,6 +11,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <algorithm>
#include <string>
#include <vector>
@@ -21,12 +22,20 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/posix/unix_domain_socket_linux.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
+class BrokerProcessTestHelper {
+ public:
+ static int get_ipc_socketpair(const BrokerProcess* broker) {
+ return broker->ipc_socketpair_;
+ }
+};
+
namespace {
// Creates and open a temporary file on creation and closes
@@ -434,4 +443,54 @@ TEST(BrokerProcess, OpenComplexFlagsNoClientCheck) {
// expected.
}
+// We need to allow noise because the broker will log when it receives our
+// bogus IPCs.
+SANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) {
+ // Find the four lowest available file descriptors.
+ int available_fds[4];
+ SANDBOX_ASSERT(0 == pipe(available_fds));
+ SANDBOX_ASSERT(0 == pipe(available_fds + 2));
+
+ // Save one FD to send to the broker later, and close the others.
+ base::ScopedFD message_fd(available_fds[0]);
+ for (size_t i = 1; i < arraysize(available_fds); i++) {
+ SANDBOX_ASSERT(0 == IGNORE_EINTR(close(available_fds[i])));
+ }
+
+ // Lower our file descriptor limit to just allow three more file descriptors
+ // to be allocated. (N.B., RLIMIT_NOFILE doesn't limit the number of file
+ // descriptors a process can have: it only limits the highest value that can
+ // be assigned to newly-created descriptors allocated by the process.)
+ const rlim_t fd_limit =
+ 1 + *std::max_element(available_fds,
+ available_fds + arraysize(available_fds));
+ const struct rlimit new_rlim = {fd_limit, fd_limit};
+ SANDBOX_ASSERT(0 == setrlimit(RLIMIT_NOFILE, &new_rlim));
+
+ static const char kCpuInfo[] = "/proc/cpuinfo";
+ std::vector<std::string> read_whitelist;
+ read_whitelist.push_back(kCpuInfo);
+
+ BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>());
+ SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback)));
+
+ const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker);
+ SANDBOX_ASSERT(ipc_fd >= 0);
+
+ static const char kBogus[] = "not a pickle";
+ std::vector<int> fds;
+ fds.push_back(message_fd.get());
+
+ // The broker process should only have a couple spare file descriptors
+ // available, but for good measure we send it fd_limit bogus IPCs anyway.
+ for (rlim_t i = 0; i < fd_limit; ++i) {
+ SANDBOX_ASSERT(
+ UnixDomainSocket::SendMsg(ipc_fd, kBogus, sizeof(kBogus), fds));
+ }
+
+ const int fd = open_broker.Open(kCpuInfo, O_RDONLY);
+ SANDBOX_ASSERT(fd >= 0);
+ SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd)));
+}
+
} // namespace sandbox
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index 2e714aa..eeb5616 100644
--- a/sandbox/linux/tests/unit_tests.cc
+++ b/sandbox/linux/tests/unit_tests.cc
@@ -208,6 +208,17 @@ void UnitTests::DeathSuccess(int status, const std::string& msg, const void*) {
EXPECT_FALSE(subprocess_exited_but_printed_messages) << details;
}
+void UnitTests::DeathSuccessAllowNoise(int status,
+ const std::string& msg,
+ const void*) {
+ std::string details(TestFailedMessage(msg));
+
+ bool subprocess_terminated_normally = WIFEXITED(status);
+ ASSERT_TRUE(subprocess_terminated_normally) << details;
+ int subprocess_exit_status = WEXITSTATUS(status);
+ ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
+}
+
void UnitTests::DeathMessage(int status,
const std::string& msg,
const void* aux) {
diff --git a/sandbox/linux/tests/unit_tests.h b/sandbox/linux/tests/unit_tests.h
index 3f6092e..0cb682b 100644
--- a/sandbox/linux/tests/unit_tests.h
+++ b/sandbox/linux/tests/unit_tests.h
@@ -40,6 +40,8 @@ bool IsRunningOnValgrind();
// gtests's ASSERT_XXX() macros instead of SANDBOX_ASSERT(). See
// unit_tests.cc for examples.
#define DEATH_SUCCESS() sandbox::UnitTests::DeathSuccess, NULL
+#define DEATH_SUCCESS_ALLOW_NOISE() \
+ sandbox::UnitTests::DeathSuccessAllowNoise, NULL
#define DEATH_MESSAGE(msg) \
sandbox::UnitTests::DeathMessage, \
static_cast<const void*>(static_cast<const char*>(msg))
@@ -68,6 +70,11 @@ bool IsRunningOnValgrind();
#define SANDBOX_TEST(test_case_name, test_name) \
SANDBOX_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS())
+// SANDBOX_TEST_ALLOW_NOISE is just like SANDBOX_TEST, except it does not
+// consider log error messages printed by the test to be test failures.
+#define SANDBOX_TEST_ALLOW_NOISE(test_case_name, test_name) \
+ SANDBOX_DEATH_TEST(test_case_name, test_name, DEATH_SUCCESS_ALLOW_NOISE())
+
// Simple assertion macro that is compatible with running inside of a death
// test. We unfortunately cannot use any of the GTest macros.
#define SANDBOX_STR(x) #x
@@ -109,6 +116,12 @@ class UnitTests {
// of this DeathCheck is unused (and thus unnamed)
static void DeathSuccess(int status, const std::string& msg, const void*);
+ // A DeathCheck method that verifies that the test completed succcessfully
+ // allowing for log error messages.
+ static void DeathSuccessAllowNoise(int status,
+ const std::string& msg,
+ const void*);
+
// A DeathCheck method that verifies that the test completed with error
// code "1" and printed a message containing a particular substring. The
// "aux" pointer should point to a C-string containing the expected error
diff --git a/sandbox/linux/tests/unit_tests_unittest.cc b/sandbox/linux/tests/unit_tests_unittest.cc
index 5ec5648..78a3645 100644
--- a/sandbox/linux/tests/unit_tests_unittest.cc
+++ b/sandbox/linux/tests/unit_tests_unittest.cc
@@ -8,6 +8,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "sandbox/linux/tests/unit_tests.h"
@@ -33,6 +34,10 @@ SANDBOX_DEATH_TEST(UnitTests,
raise(kExpectedSignalNumber);
}
+SANDBOX_TEST_ALLOW_NOISE(UnitTests, NoisyTest) {
+ LOG(ERROR) << "The cow says moo!";
+}
+
// Test that a subprocess can be forked() and can use exit(3) instead of
// _exit(2).
TEST(UnitTests, SubProcessCanExit) {