diff options
author | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-20 06:23:48 +0000 |
---|---|---|
committer | mseaborn@chromium.org <mseaborn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-20 06:23:48 +0000 |
commit | a77d3fa28aac20b463fcf8a1339d30acc7c27fc1 (patch) | |
tree | 7e9baf91ab81505361d13a1b42320a45fe1c452e /sandbox | |
parent | 5575f886246827b500ef2e92947c5a18fd8dd204 (diff) | |
download | chromium_src-a77d3fa28aac20b463fcf8a1339d30acc7c27fc1.zip chromium_src-a77d3fa28aac20b463fcf8a1339d30acc7c27fc1.tar.gz chromium_src-a77d3fa28aac20b463fcf8a1339d30acc7c27fc1.tar.bz2 |
NaCl: Add sanity check for number of open FDs at startup
This is primarily for Non-SFI NaCl, where leaking FDs would be a
security hole. For SFI NaCl, this is just for defence in depth.
I've put the check just before enabling the seccomp-bpf sandbox. This
guards against creation of unusual FDs, e.g. via epoll_create(), which
might happen even after enabling the SUID sandbox (which mostly disables
open()).
BUG=358719
TEST=browser_tests
Review URL: https://codereview.chromium.org/276443003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271583 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sandbox')
-rw-r--r-- | sandbox/linux/services/credentials.cc | 29 | ||||
-rw-r--r-- | sandbox/linux/services/credentials.h | 5 | ||||
-rw-r--r-- | sandbox/linux/services/credentials_unittest.cc | 12 |
3 files changed, 46 insertions, 0 deletions
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc index 51a535d..96702b1 100644 --- a/sandbox/linux/services/credentials.cc +++ b/sandbox/linux/services/credentials.cc @@ -173,6 +173,35 @@ Credentials::Credentials() { Credentials::~Credentials() { } +int Credentials::CountOpenFds(int proc_fd) { + DCHECK_LE(0, proc_fd); + int proc_self_fd = openat(proc_fd, "self/fd", O_DIRECTORY | O_RDONLY); + PCHECK(0 <= proc_self_fd); + + // Ownership of proc_self_fd is transferred here, it must not be closed + // or modified afterwards except via dir. + ScopedDIR dir(fdopendir(proc_self_fd)); + CHECK(dir); + + int count = 0; + struct dirent e; + struct dirent* de; + while (!readdir_r(dir.get(), &e, &de) && de) { + if (strcmp(e.d_name, ".") == 0 || strcmp(e.d_name, "..") == 0) { + continue; + } + + int fd_num; + CHECK(base::StringToInt(e.d_name, &fd_num)); + if (fd_num == proc_fd || fd_num == proc_self_fd) { + continue; + } + + ++count; + } + return count; +} + bool Credentials::HasOpenDirectory(int proc_fd) { int proc_self_fd = -1; if (proc_fd >= 0) { diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h index 56ff115..99f8f32 100644 --- a/sandbox/linux/services/credentials.h +++ b/sandbox/linux/services/credentials.h @@ -27,6 +27,11 @@ class SANDBOX_EXPORT Credentials { Credentials(); ~Credentials(); + // Returns the number of file descriptors in the current process's FD + // table, excluding |proc_fd|, which should be a file descriptor for + // /proc. + int CountOpenFds(int proc_fd); + // Checks whether the current process has any directory file descriptor open. // Directory file descriptors are "capabilities" that would let a process use // system calls such as openat() to bypass restrictions such as diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc index a54ed04..c701b9b 100644 --- a/sandbox/linux/services/credentials_unittest.cc +++ b/sandbox/linux/services/credentials_unittest.cc @@ -57,6 +57,18 @@ TEST(Credentials, CreateAndDestroy) { scoped_ptr<Credentials> cred2(new Credentials); } +TEST(Credentials, CountOpenFds) { + base::ScopedFD proc_fd(open("/proc", O_RDONLY | O_DIRECTORY)); + ASSERT_TRUE(proc_fd.is_valid()); + Credentials creds; + int fd_count = creds.CountOpenFds(proc_fd.get()); + int fd = open("/dev/null", O_RDONLY); + ASSERT_LE(0, fd); + EXPECT_EQ(fd_count + 1, creds.CountOpenFds(proc_fd.get())); + ASSERT_EQ(0, IGNORE_EINTR(close(fd))); + EXPECT_EQ(fd_count, creds.CountOpenFds(proc_fd.get())); +} + TEST(Credentials, HasOpenDirectory) { Credentials creds; // No open directory should exist at startup. |