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 <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);
|
||||
|
Reference in New Issue
Block a user