Home | History | Annotate | Download | only in renderer_host
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
      6 
      7 #include <sys/socket.h>
      8 
      9 #include "base/memory/singleton.h"
     10 #include "base/posix/eintr_wrapper.h"
     11 
     12 namespace content {
     13 
     14 // Runs on the main thread at startup.
     15 RenderSandboxHostLinux::RenderSandboxHostLinux()
     16     : initialized_(false), renderer_socket_(0), childs_lifeline_fd_(0) {
     17 }
     18 
     19 // static
     20 RenderSandboxHostLinux* RenderSandboxHostLinux::GetInstance() {
     21   return Singleton<RenderSandboxHostLinux>::get();
     22 }
     23 
     24 void RenderSandboxHostLinux::Init() {
     25   DCHECK(!initialized_);
     26   initialized_ = true;
     27 
     28   int fds[2];
     29   // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the renderer from
     30   // sending datagrams to other sockets on the system. The sandbox may prevent
     31   // the renderer from calling socket() to create new sockets, but it'll still
     32   // inherit some sockets. With AF_UNIX+SOCK_DGRAM, it can call sendmsg to send
     33   // a datagram to any (abstract) socket on the same system. With
     34   // SOCK_SEQPACKET, this is prevented.
     35   CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
     36 
     37   renderer_socket_ = fds[0];
     38   // The SandboxIPC client is not expected to read from |renderer_socket_|.
     39   // Instead, it reads from a temporary socket sent with the request.
     40   PCHECK(0 == shutdown(renderer_socket_, SHUT_RD)) << "shutdown";
     41 
     42   const int browser_socket = fds[1];
     43   // The SandboxIPC handler is not expected to write to |browser_socket|.
     44   // Instead, it replies on a temporary socket provided by the caller.
     45   PCHECK(0 == shutdown(browser_socket, SHUT_WR)) << "shutdown";
     46 
     47   int pipefds[2];
     48   CHECK(0 == pipe(pipefds));
     49   const int child_lifeline_fd = pipefds[0];
     50   childs_lifeline_fd_ = pipefds[1];
     51 
     52   ipc_handler_.reset(
     53       new SandboxIPCHandler(child_lifeline_fd, browser_socket));
     54   ipc_thread_.reset(
     55       new base::DelegateSimpleThread(ipc_handler_.get(), "sandbox_ipc_thread"));
     56   ipc_thread_->Start();
     57 }
     58 
     59 bool RenderSandboxHostLinux::ShutdownIPCChannel() {
     60   return IGNORE_EINTR(close(childs_lifeline_fd_)) == 0;
     61 }
     62 
     63 RenderSandboxHostLinux::~RenderSandboxHostLinux() {
     64   if (initialized_) {
     65     if (!ShutdownIPCChannel())
     66       LOG(ERROR) << "ShutdownIPCChannel failed";
     67     if (IGNORE_EINTR(close(renderer_socket_)) < 0)
     68       PLOG(ERROR) << "close";
     69 
     70     ipc_thread_->Join();
     71   }
     72 }
     73 
     74 }  // namespace content
     75