| Index: content/browser/zygote_main_linux.cc
|
| diff --git a/content/browser/zygote_main_linux.cc b/content/browser/zygote_main_linux.cc
|
| index aad52839e9691ad989211561585fd1dc595fc307..10c4983e208df9284bb4620da576bd2b4cdda9ca 100644
|
| --- a/content/browser/zygote_main_linux.cc
|
| +++ b/content/browser/zygote_main_linux.cc
|
| @@ -96,6 +96,10 @@ class Zygote {
|
| public:
|
| Zygote(int sandbox_flags, ZygoteForkDelegate* helper)
|
| : sandbox_flags_(sandbox_flags), helper_(helper) {
|
| + if (helper_)
|
| + helper_->InitialUMA(&initial_uma_name_,
|
| + &initial_uma_sample_,
|
| + &initial_uma_boundary_value_);
|
| }
|
|
|
| bool ProcessRequests() {
|
| @@ -253,10 +257,16 @@ class Zygote {
|
| // This is equivalent to fork(), except that, when using the SUID
|
| // sandbox, it returns the real PID of the child process as it
|
| // appears outside the sandbox, rather than returning the PID inside
|
| - // the sandbox.
|
| + // the sandbox. Optionally, it fills in uma_name et al with a report
|
| + // the helper wants to make via UMA_HISTOGRAM_ENUMERATION.
|
| int ForkWithRealPid(const std::string& process_type, std::vector<int>& fds,
|
| - const std::string& channel_switch) {
|
| - const bool use_helper = (helper_ && helper_->CanHelp(process_type));
|
| + const std::string& channel_switch,
|
| + std::string* uma_name,
|
| + int* uma_sample, int* uma_boundary_value) {
|
| + const bool use_helper = (helper_ && helper_->CanHelp(process_type,
|
| + uma_name,
|
| + uma_sample,
|
| + uma_boundary_value));
|
| if (!(use_helper || g_suid_sandbox_active)) {
|
| return fork();
|
| }
|
| @@ -382,7 +392,10 @@ class Zygote {
|
| // process and the child process ID to the parent process, like fork().
|
| base::ProcessId ReadArgsAndFork(const Pickle& pickle,
|
| void* iter,
|
| - std::vector<int>& fds) {
|
| + std::vector<int>& fds,
|
| + std::string* uma_name,
|
| + int* uma_sample,
|
| + int* uma_boundary_value) {
|
| std::vector<std::string> args;
|
| int argc = 0;
|
| int numfds = 0;
|
| @@ -422,7 +435,9 @@ class Zygote {
|
| static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor));
|
|
|
| // Returns twice, once per process.
|
| - base::ProcessId child_pid = ForkWithRealPid(process_type, fds, channel_id);
|
| + base::ProcessId child_pid = ForkWithRealPid(process_type, fds, channel_id,
|
| + uma_name, uma_sample,
|
| + uma_boundary_value);
|
| if (!child_pid) {
|
| // This is the child process.
|
| #if defined(SECCOMP_SANDBOX)
|
| @@ -470,14 +485,36 @@ class Zygote {
|
| // child_pid of -1 on error.
|
| bool HandleForkRequest(int fd, const Pickle& pickle,
|
| void* iter, std::vector<int>& fds) {
|
| - base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds);
|
| + std::string uma_name;
|
| + int uma_sample;
|
| + int uma_boundary_value;
|
| + base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds,
|
| + &uma_name, &uma_sample,
|
| + &uma_boundary_value);
|
| if (child_pid == 0)
|
| return true;
|
| for (std::vector<int>::const_iterator
|
| i = fds.begin(); i != fds.end(); ++i)
|
| close(*i);
|
| + if (uma_name.empty()) {
|
| + // There is no UMA report from this particular fork.
|
| + // Use the initial UMA report if any, and clear that record for next time.
|
| + // Note the swap method here is the efficient way to do this, since
|
| + // we know uma_name is empty.
|
| + uma_name.swap(initial_uma_name_);
|
| + uma_sample = initial_uma_sample_;
|
| + uma_boundary_value = initial_uma_boundary_value_;
|
| + }
|
| // Must always send reply, as ZygoteHost blocks while waiting for it.
|
| - if (HANDLE_EINTR(write(fd, &child_pid, sizeof(child_pid))) < 0)
|
| + Pickle reply_pickle;
|
| + reply_pickle.WriteInt(child_pid);
|
| + reply_pickle.WriteString(uma_name);
|
| + if (!uma_name.empty()) {
|
| + reply_pickle.WriteInt(uma_sample);
|
| + reply_pickle.WriteInt(uma_boundary_value);
|
| + }
|
| + if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) !=
|
| + static_cast<ssize_t> (reply_pickle.size()))
|
| PLOG(ERROR) << "write";
|
| return false;
|
| }
|
| @@ -499,6 +536,12 @@ class Zygote {
|
|
|
| const int sandbox_flags_;
|
| ZygoteForkDelegate* helper_;
|
| +
|
| + // These might be set by helper_->InitialUMA. They supply a UMA
|
| + // enumeration sample we should report on the first fork.
|
| + std::string initial_uma_name_;
|
| + int initial_uma_sample_;
|
| + int initial_uma_boundary_value_;
|
| };
|
|
|
| // With SELinux we can carve out a precise sandbox, so we don't have to play
|
|
|