chromium/components/crash/core/app/crashpad_linux.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/crash/core/app/crashpad.h"

#include <pthread.h>
#include <sys/prctl.h>

#include <limits>

#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/linux_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "build/branding_buildflags.h"
#include "build/chromeos_buildflags.h"
#include "components/crash/core/app/crash_reporter_client.h"
#include "components/crash/core/app/crash_switches.h"
#include "content/public/common/content_descriptors.h"
#include "sandbox/linux/services/namespace_sandbox.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
#include "third_party/crashpad/crashpad/client/crashpad_info.h"

#if BUILDFLAG(IS_CHROMEOS_DEVICE)
#include <sys/types.h>
#include <unistd.h>

#include <utility>

#include "base/at_exit.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "third_party/cros_system_api/constants/crash_reporter.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "base/build_time.h"
#endif

namespace crash_reporter {

namespace {

// TODO(jperaza): This is the first chance handler type used by Breakpad and v8.
// The Crashpad FirstChanceHandler type explicitly declares the third parameter
// to be a ucontext_t* instead of a void*. Using a reinterpret cast to convert
// one function type to another causes calling the handler to fail with SIGILL
// when CFI is enabled. Use a helper with Crashpad's FirstChanceHandler type
// to delegate to the real first chance handler instead of re-interpreting the
// handler itself. This can be removed if the two function types converge.
bool (*g_first_chance_handler)(int, siginfo_t*, void*);

bool FirstChanceHandlerHelper(int signo,
                              siginfo_t* siginfo,
                              ucontext_t* context) {}

#if BUILDFLAG(IS_CHROMEOS_DEVICE)
// Returns /run/crash_reporter/crashpad_ready/<pid>, the file we touch to
// tell crash_reporter that crashpad is ready and it doesn't need to use
// early-crash mode.
base::FilePath GetCrashpadReadyFilename() {
  pid_t pid = getpid();
  base::FilePath path(crash_reporter::kCrashpadReadyDirectory);
  return path.Append(base::NumberToString(pid));
}

// Inform crash_reporter than crashpad is ready to handle crashes by
// touching /run/crash_reporter/crashpad_ready/<pid>.
//
// Before this point, crash_reporter will attempt to handle Chrome crashes
// sent to it by the kernel core_pattern. This gives us a chance to catch
// crashes that happen before crashpad initializes. See code around
// UserCollector::handling_early_chrome_crash_ for details. Once the
// /run/crash_reporter/crashpad_ready/<pid> file exists, however,
// crash_reporter's UserCollector will assume crashpad will deal with the
// crash and can early-return.
//
// We only need this for the browser process; the cores are too large for
// other processes so early crash doesn't attempt to handle them.
void InformCrashReporterThatCrashpadIsReady() {
  base::FilePath path = GetCrashpadReadyFilename();
  // Note: Using a base::File with FLAG_CREATE instead of WriteFile() to
  // avoid symbolic link shenanigans.
  base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  if (!file.IsValid()) {
    LOG(ERROR) << "Could not create " << path << ": "
               << base::File::ErrorToString(file.error_details());
  }

  // Remove file when the program exits. This isn't perfect; if the program
  // crashes, and if the next browser process comes up with the same PID
  // (without an intervening reboot), and that browser process crashes before
  // crashpad initializes, then the crash service won't get the crash report.
  // This is unlikely enough that I think we can risk it, especially since
  // losing a single crash report is not a huge deal.
  base::AtExitManager::RegisterTask(base::BindOnce(&DeleteCrashpadIsReadyFile));
}
#endif  // BUILDFLAG(IS_CHROMEOS_DEVICE)

}  // namespace

void SetFirstChanceExceptionHandler(bool (*handler)(int, siginfo_t*, void*)) {}

bool GetHandlerSocket(int* fd, pid_t* pid) {}

#if BUILDFLAG(IS_CHROMEOS_DEVICE)
void DeleteCrashpadIsReadyFile() {
  // Attempt delete but do not log errors if the delete fails. The file might
  // not exist if this function is called twice, or if Chrome did a fork-
  // without-exec and this function is not in the same process that called
  // InformCrashReporterThatCrashpadIsReady().
  base::DeleteFile(GetCrashpadReadyFilename());
}
#endif  // BUILDFLAG(IS_CHROMEOS_DEVICE)

namespace internal {

bool PlatformCrashpadInitialization(
    bool initial_client,
    bool browser_process,
    bool embedded_handler,
    const std::string& user_data_dir,
    const base::FilePath& exe_path,
    const std::vector<std::string>& initial_arguments,
    base::FilePath* database_path) {}

}  // namespace internal
}  // namespace crash_reporter