0

POSIX: make sure that we never pass directory descriptors into the sandbox.

BUG=43304

http://codereview.chromium.org/2733011/show

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49446 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
agl@chromium.org
2010-06-10 21:39:04 +00:00
parent dc78796d35
commit aac449e715
4 changed files with 37 additions and 1 deletions

@ -4,9 +4,11 @@
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <time.h>
@ -369,8 +371,15 @@ class SandboxIPCProcess {
char control_buffer[CMSG_SPACE(sizeof(int))];
if (reply_fd != -1) {
struct cmsghdr *cmsg;
struct stat st;
if (fstat(reply_fd, &st) == 0 && S_ISDIR(st.st_mode)) {
LOG(FATAL) << "Tried to send a directory descriptor over sandbox IPC";
// We must never send directory descriptors to a sandboxed process
// because they can use openat with ".." elements in the path in order
// to escape the sandbox and reach the real filesystem.
}
struct cmsghdr *cmsg;
msg.msg_control = control_buffer;
msg.msg_controllen = sizeof(control_buffer);
cmsg = CMSG_FIRSTHDR(&msg);

@ -4,6 +4,9 @@
#include "ipc/file_descriptor_set_posix.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "base/eintr_wrapper.h"
#include "base/logging.h"
@ -94,6 +97,18 @@ void FileDescriptorSet::GetDescriptors(int* buffer) const {
}
}
bool FileDescriptorSet::ContainsDirectoryDescriptor() const {
struct stat st;
for (std::vector<base::FileDescriptor>::const_iterator
i = descriptors_.begin(); i != descriptors_.end(); ++i) {
if (fstat(i->fd, &st) == 0 && S_ISDIR(st.st_mode))
return true;
}
return false;
}
void FileDescriptorSet::CommitAll() {
for (std::vector<base::FileDescriptor>::iterator
i = descriptors_.begin(); i != descriptors_.end(); ++i) {

@ -74,6 +74,9 @@ class FileDescriptorSet : public base::RefCountedThreadSafe<FileDescriptorSet> {
// GetDescriptors. It marks all the descriptors as consumed and closes those
// which are auto-close.
void CommitAll();
// Returns true if any contained file descriptors appear to be handles to a
// directory.
bool ContainsDirectoryDescriptor() const;
// ---------------------------------------------------------------------------

@ -791,6 +791,15 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
const unsigned num_fds = msg->file_descriptor_set()->size();
DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE);
if (msg->file_descriptor_set()->ContainsDirectoryDescriptor()) {
LOG(FATAL) << "Panic: attempting to transport directory descriptor over"
" IPC. Aborting to maintain sandbox isolation.";
// If you have hit this then something tried to send a file descriptor
// to a directory over an IPC channel. Since IPC channels span
// sandboxes this is very bad: the receiving process can use openat
// with ".." elements in the path in order to reach the real
// filesystem.
}
msgh.msg_control = buf;
msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);