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#ifndef CONTENT_ZYGOTE_ZYGOTE_H_
6#define CONTENT_ZYGOTE_ZYGOTE_H_
7
8#include <string>
9#include <vector>
10
11#include "base/containers/hash_tables.h"
12#include "base/process/process.h"
13
14class Pickle;
15class PickleIterator;
16
17namespace content {
18
19class ZygoteForkDelegate;
20
21// This is the object which implements the zygote. The ZygoteMain function,
22// which is called from ChromeMain, simply constructs one of these objects and
23// runs it.
24class Zygote {
25 public:
26  Zygote(int sandbox_flags,
27         ZygoteForkDelegate* helper);
28  ~Zygote();
29
30  bool ProcessRequests();
31
32  static const int kBrowserDescriptor = 3;
33  static const int kMagicSandboxIPCDescriptor = 5;
34
35 private:
36  // Returns true if the SUID sandbox is active.
37  bool UsingSUIDSandbox() const;
38
39  // ---------------------------------------------------------------------------
40  // Requests from the browser...
41
42  // Read and process a request from the browser. Returns true if we are in a
43  // new process and thus need to unwind back into ChromeMain.
44  bool HandleRequestFromBrowser(int fd);
45
46  void HandleReapRequest(int fd, const Pickle& pickle, PickleIterator iter);
47
48  void HandleGetTerminationStatus(int fd,
49                                  const Pickle& pickle,
50                                  PickleIterator iter);
51
52  // This is equivalent to fork(), except that, when using the SUID sandbox, it
53  // returns the real PID of the child process as it appears outside the
54  // sandbox, rather than returning the PID inside the sandbox. Optionally, it
55  // fills in uma_name et al with a report the helper wants to make via
56  // UMA_HISTOGRAM_ENUMERATION.
57  int ForkWithRealPid(const std::string& process_type,
58                      std::vector<int>& fds,
59                      const std::string& channel_switch,
60                      std::string* uma_name,
61                      int* uma_sample,
62                      int* uma_boundary_value);
63
64  // Unpacks process type and arguments from |pickle| and forks a new process.
65  // Returns -1 on error, otherwise returns twice, returning 0 to the child
66  // process and the child process ID to the parent process, like fork().
67  base::ProcessId ReadArgsAndFork(const Pickle& pickle,
68                                  PickleIterator iter,
69                                  std::vector<int>& fds,
70                                  std::string* uma_name,
71                                  int* uma_sample,
72                                  int* uma_boundary_value);
73
74  // Handle a 'fork' request from the browser: this means that the browser
75  // wishes to start a new renderer. Returns true if we are in a new process,
76  // otherwise writes the child_pid back to the browser via |fd|. Writes a
77  // child_pid of -1 on error.
78  bool HandleForkRequest(int fd,
79                         const Pickle& pickle,
80                         PickleIterator iter,
81                         std::vector<int>& fds);
82
83  bool HandleGetSandboxStatus(int fd,
84                              const Pickle& pickle,
85                              PickleIterator iter);
86
87  // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs
88  // fork() returns are not the real PIDs, so we need to map the Real PIDS
89  // into the sandbox PID namespace.
90  typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap;
91  ProcessMap real_pids_to_sandbox_pids;
92
93  const int sandbox_flags_;
94  ZygoteForkDelegate* helper_;
95
96  // These might be set by helper_->InitialUMA. They supply a UMA enumeration
97  // sample we should report on the first fork.
98  std::string initial_uma_name_;
99  int initial_uma_sample_;
100  int initial_uma_boundary_value_;
101};
102
103}  // namespace content
104
105#endif  // CONTENT_ZYGOTE_ZYGOTE_H_
106