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:
chrome/browser/renderer_host
ipc
@@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
|
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -369,8 +371,15 @@ class SandboxIPCProcess {
|
|||||||
char control_buffer[CMSG_SPACE(sizeof(int))];
|
char control_buffer[CMSG_SPACE(sizeof(int))];
|
||||||
|
|
||||||
if (reply_fd != -1) {
|
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_control = control_buffer;
|
||||||
msg.msg_controllen = sizeof(control_buffer);
|
msg.msg_controllen = sizeof(control_buffer);
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#include "ipc/file_descriptor_set_posix.h"
|
#include "ipc/file_descriptor_set_posix.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "base/eintr_wrapper.h"
|
#include "base/eintr_wrapper.h"
|
||||||
#include "base/logging.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() {
|
void FileDescriptorSet::CommitAll() {
|
||||||
for (std::vector<base::FileDescriptor>::iterator
|
for (std::vector<base::FileDescriptor>::iterator
|
||||||
i = descriptors_.begin(); i != descriptors_.end(); ++i) {
|
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
|
// GetDescriptors. It marks all the descriptors as consumed and closes those
|
||||||
// which are auto-close.
|
// which are auto-close.
|
||||||
void CommitAll();
|
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();
|
const unsigned num_fds = msg->file_descriptor_set()->size();
|
||||||
|
|
||||||
DCHECK_LE(num_fds, FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE);
|
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_control = buf;
|
||||||
msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
msgh.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||||
|
Reference in New Issue
Block a user