15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_sandbox_host_linux.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/socket.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Runs on the main thread at startup.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderSandboxHostLinux::RenderSandboxHostLinux()
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : initialized_(false), renderer_socket_(0), childs_lifeline_fd_(0) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderSandboxHostLinux* RenderSandboxHostLinux::GetInstance() {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Singleton<RenderSandboxHostLinux>::get();
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderSandboxHostLinux::Init() {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!initialized_);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized_ = true;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fds[2];
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the renderer from
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sending datagrams to other sockets on the system. The sandbox may prevent
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the renderer from calling socket() to create new sockets, but it'll still
320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // inherit some sockets. With AF_UNIX+SOCK_DGRAM, it can call sendmsg to send
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a datagram to any (abstract) socket on the same system. With
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOCK_SEQPACKET, this is prevented.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  renderer_socket_ = fds[0];
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The SandboxIPC client is not expected to read from |renderer_socket_|.
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Instead, it reads from a temporary socket sent with the request.
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PCHECK(0 == shutdown(renderer_socket_, SHUT_RD)) << "shutdown";
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int browser_socket = fds[1];
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The SandboxIPC handler is not expected to write to |browser_socket|.
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Instead, it replies on a temporary socket provided by the caller.
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  PCHECK(0 == shutdown(browser_socket, SHUT_WR)) << "shutdown";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipefds[2];
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(0 == pipe(pipefds));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int child_lifeline_fd = pipefds[0];
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  childs_lifeline_fd_ = pipefds[1];
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ipc_handler_.reset(
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SandboxIPCHandler(child_lifeline_fd, browser_socket));
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ipc_thread_.reset(
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new base::DelegateSimpleThread(ipc_handler_.get(), "sandbox_ipc_thread"));
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ipc_thread_->Start();
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RenderSandboxHostLinux::ShutdownIPCChannel() {
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return IGNORE_EINTR(close(childs_lifeline_fd_)) == 0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderSandboxHostLinux::~RenderSandboxHostLinux() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized_) {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!ShutdownIPCChannel())
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(ERROR) << "ShutdownIPCChannel failed";
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(renderer_socket_)) < 0)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(ERROR) << "close";
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ipc_thread_->Join();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
75