Commit ab224140 authored by Joshua Peraza's avatar Joshua Peraza Committed by Commit Bot

Reland "Package Crashpad's handler into various APKs"

This is a reland of dbca191e

Original change's description:
> Package Crashpad's handler into various APKs
>
> For Chromecast, Content Shell, and non-monochrome Clank/Webview:
>
> The Crashpad handler is a standalone executable, packaged like a
> loadable module and named libcrashpad_handler.so in order to not be
> ignored by Android's APK installer.
>
> For Monochrome:
>
> The Crashpad handler is linked into libmonochrome.so. At crash-time
> /system/bin/app_process{32,64} is exec-ed, running CrashpadMain.java
> which loads libmonochrome.so and runs the native HandlerMain().
>
> This strategy is not used for non-monochrome APKs (i.e. pre-N) because
> on L, Android's loader is not yet capable of loading native libraries
> from the APK. This is normally performed by the Chromium linker which
> can't be used by CrashpadMain.java because /system/bin/app_process
> doesn't initialize the process like a normal Android application
> (specifically, no ContextImpl has been created, so any calls to e.g.
> appContext.getApplicationInfo() will segfault).
>
> Binary-Size: MonochromePublic.apk increases in size by 100 KB.
> ChromeModernPublic.apk increases in size by 203KB (587 KB
> increase in install size because libcrashpad_handler.so is extracted
> from the APK). Possible mitigations for this increase are TODO:
>
> For J, K: We could link the handler directly into libchrome.so and let
> that be our handler executable. This would de-dup portions of libbase
> that are currently linked into both libchrome.so and
> libcrashpad_handler.so.
>
> For L, M: It might be possible to get the chromium linker (or Bionic's
> linker on M) to dlopen libchrome.so from the APK for a trampoline
> libcrashpad_handler.so to de-dup libbase.
>
> Bug: crashpad:30
> Change-Id: If5b3752f26455e5c7aef3278b4bd2076ef1b7b65
> Reviewed-on: https://chromium-review.googlesource.com/1150774
> Reviewed-by: Bo <boliu@chromium.org>
> Reviewed-by: agrieve <agrieve@chromium.org>
> Reviewed-by: Mark Mentovai <mark@chromium.org>
> Reviewed-by: Richard Coles <torne@chromium.org>
> Reviewed-by: Luke Halliwell <halliwell@chromium.org>
> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#594853}

TBR=agieve@chromium.org,torne@chromium.org

Binary-Size: See above.
Bug: crashpad:30
Change-Id: I2b866be642670188d9e8b674fac940b05497b806
Reviewed-on: https://chromium-review.googlesource.com/c/1252007
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Reviewed-by: default avatarYaron Friedman <yfriedman@chromium.org>
Reviewed-by: default avatarLuke Halliwell <halliwell@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612950}
parent c15f3499
......@@ -429,6 +429,7 @@ if (android_64bit_target_cpu) {
shared_library("monochrome") {
deps = [
":webview_entry_point",
"//components/crash/android:crashpad_main",
]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ]
......
......@@ -18,8 +18,11 @@ template("system_webview_apk_tmpl") {
"//android_webview/glue",
"//android_webview/support_library:support_lib_glue_java",
"//base:base_java",
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
]
loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
if (!defined(alternative_android_sdk_dep)) {
alternative_android_sdk_dep = webview_framework_dep
}
......@@ -30,6 +33,12 @@ template("system_webview_apk_tmpl") {
shared_libraries = [ "//android_webview:libwebviewchromium" ]
if (build_apk_secondary_abi && android_64bit_target_cpu) {
secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
deps += [ "//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so($android_secondary_abi_toolchain)" ]
toolchain_out_dir = get_label_info(
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so($android_secondary_abi_toolchain)",
"root_out_dir")
secondary_abi_loadable_modules =
[ "${toolchain_out_dir}/libcrashpad_handler.so" ]
}
} else {
# Include placeholder libraries to ensure we are treated as the desired
......
......@@ -52,6 +52,7 @@ android_apk("webview_instrumentation_apk") {
"//components/policy/android:policy_java_test_support",
"//content/public/android:content_java",
"//third_party/android_support_test_runner:runner_java",
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
"//third_party/junit",
"//ui/android:ui_java",
]
......@@ -78,6 +79,8 @@ android_apk("webview_instrumentation_apk") {
":libstandalonelibwebviewchromium",
]
loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
native_lib_version_rule = "//build/util:chrome_version_json"
_native_lib_file =
rebase_path("$root_gen_dir/CHROME_VERSION.json", root_build_dir)
......
......@@ -212,7 +212,8 @@ def _AddNativeLibraries(out_apk, native_libs, android_abi, uncompress):
compress = None
if (uncompress and os.path.splitext(basename)[1] == '.so'
and 'android_linker' not in basename
and 'clang_rt' not in basename):
and 'clang_rt' not in basename
and 'crashpad_handler' not in basename):
compress = False
# Add prefix to prevent android install from extracting upon install.
if has_crazy_linker:
......
......@@ -1340,6 +1340,7 @@ if (!android_64bit_target_cpu ||
]
deps = [
"//android_webview:common",
"//components/crash/android:crashpad_main",
]
export_java_symbols = true
......
......@@ -93,6 +93,8 @@ template("chrome_public_common_apk_or_module_tmpl") {
_is_modern = defined(invoker.is_modern) && invoker.is_modern
assert(_is_modern || !_is_modern) # Mark as used.
_is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
if (defined(invoker.enable_multidex)) {
_enable_multidex = invoker.enable_multidex
} else {
......@@ -127,6 +129,16 @@ template("chrome_public_common_apk_or_module_tmpl") {
aapt_locale_whitelist = locales - android_chrome_omitted_locales
}
if (!_is_monochrome) {
deps += [
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
]
if (!defined(loadable_modules)) {
loadable_modules = []
}
loadable_modules += [ "$root_out_dir/libcrashpad_handler.so" ]
}
if (_enable_multidex) {
enable_multidex = true
if (_target_type == "android_apk") {
......@@ -216,6 +228,8 @@ template("monochrome_public_common_apk_or_module_tmpl") {
_enable_multidex = is_java_debug || multidex_in_release
}
chrome_public_common_apk_or_module_tmpl(target_name) {
is_monochrome = true
if (!defined(invoker.use_trichrome_library) ||
!invoker.use_trichrome_library) {
# Always build 64-bit //android_webview:monochrome because Chrome runs
......@@ -284,6 +298,7 @@ template("monochrome_public_common_apk_or_module_tmpl") {
"//chrome/android:chrome_public_non_pak_assets",
"//chrome/android:monochrome_apk_pak_assets",
"//chrome/android/monochrome:monochrome_license_provider_java",
"//components/crash/android:handler_java",
]
if (_enable_multidex && invoker.target_type == "android_apk" &&
......
......@@ -25,6 +25,7 @@ CHROME_SPECIFIC = BuildFileMatchRegex(
r'lib/.*/libchrome\.\d{4}\.\d{2,3}\.so', # libchrome placeholders
r'lib/.*/libchromium_android_linker\.so',
r'lib/.*/libchromeview\.so', # placeholder library
r'lib/.*/libcrashpad_handler\.so',
r'lib/.*/crazy\.libchrome\.so',
r'lib/.*/crazy\.libchrome\.align',
r'lib/.*/gdbserver',
......@@ -38,6 +39,7 @@ CHROME_SPECIFIC = BuildFileMatchRegex(
# WebView specific files which are not in Monochrome.apk
WEBVIEW_SPECIFIC = BuildFileMatchRegex(
r'lib/.*/libcrashpad_handler\.so',
r'lib/.*/libwebviewchromium\.so',
r'assets/webview_licenses.notice',
r'res/.*/icon_webview.webp',
......
......@@ -644,8 +644,11 @@ if (is_android) {
"//base:base_java",
"//chromecast/android:libcast_shell_android",
"//chromecast/browser/android:cast_shell_java",
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
]
loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
command_line_flags_file = "castshell-command-line"
}
}
......@@ -64,3 +64,31 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
_java_handler_jni_sources =
[ "java/src/org/chromium/components/crash/browser/CrashpadMain.java" ]
generate_jni("java_handler_jni_headers") {
sources = _java_handler_jni_sources
jni_package = "crashpad"
}
android_library("handler_java") {
deps = [
"//base:base_java",
]
java_files = _java_handler_jni_sources
}
static_library("crashpad_main") {
sources = [
"crashpad_main.cc",
]
deps = [
":java_handler_jni_headers",
"//base",
"//third_party/crashpad/crashpad/client",
"//third_party/crashpad/crashpad/handler",
]
}
include_rules = [
"+jni",
]
\ No newline at end of file
"+third_party/crashpad",
]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "jni/CrashpadMain_jni.h"
#include "third_party/crashpad/crashpad/client/client_argv_handling.h"
#include "third_party/crashpad/crashpad/handler/handler_main.h"
namespace crashpad {
static void JNI_CrashpadMain_CrashpadMain(
JNIEnv* env,
const base::android::JavaParamRef<jobjectArray>& j_argv) {
std::vector<std::string> argv_strings;
base::android::AppendJavaStringArrayToStringVector(env, j_argv,
&argv_strings);
std::vector<const char*> argv;
StringVectorToCStringVector(argv_strings, &argv);
HandlerMain(argv.size() - 1, const_cast<char**>(argv.data()), nullptr);
}
} // namespace crashpad
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.components.crash.browser;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.UsedByReflection;
import org.chromium.base.library_loader.NativeLibraries;
@JNINamespace("crashpad")
final class CrashpadMain {
@UsedByReflection("crashpad_linux.cc")
public static void main(String[] argv) {
try {
for (String library : NativeLibraries.LIBRARIES) {
System.loadLibrary(library);
}
} catch (UnsatisfiedLinkError e) {
throw new RuntimeException(e);
}
nativeCrashpadMain(argv);
}
private static native void nativeCrashpadMain(String[] argv);
}
......@@ -26,6 +26,7 @@
#include "content/public/common/content_descriptors.h"
#include "sandbox/linux/services/syscall_wrappers.h"
#include "third_party/crashpad/crashpad/client/annotation.h"
#include "third_party/crashpad/crashpad/client/client_argv_handling.h"
#include "third_party/crashpad/crashpad/client/crashpad_client.h"
#include "third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information.h"
#include "third_party/crashpad/crashpad/util/linux/exception_handler_client.h"
......@@ -36,6 +37,7 @@
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#include "base/android/java_exception_reporter.h"
#include "base/android/path_utils.h"
#endif // OS_ANDROID
namespace crashpad {
......@@ -82,6 +84,12 @@ class SandboxedHandler {
base::ScopedFD local_connection(fds[0]);
base::ScopedFD handlers_socket(fds[1]);
// SELinux may block the handler from setting SO_PASSCRED on this socket.
// Attempt to set it here, but the handler can still try if this fails.
int optval = 1;
socklen_t optlen = sizeof(optval);
setsockopt(handlers_socket.get(), SOL_SOCKET, SO_PASSCRED, &optval, optlen);
iovec iov;
iov.iov_base = &signo;
iov.iov_len = sizeof(signo);
......@@ -186,9 +194,64 @@ void SetBuildInfoAnnotations(std::map<std::string, std::string>* annotations) {
}
}
#if defined(__arm__) && defined(__ARM_ARCH_7A__)
#define CURRENT_ABI "armeabi-v7a"
#elif defined(__arm__)
#define CURRENT_ABI "armeabi"
#elif defined(__i386__)
#define CURRENT_ABI "x86"
#elif defined(__mips__)
#define CURRENT_ABI "mips"
#elif defined(__x86_64__)
#define CURRENT_ABI "x86_64"
#elif defined(__aarch64__)
#define CURRENT_ABI "arm64-v8a"
#else
#error "Unsupported target abi"
#endif
// Copies and extends the current environment with CLASSPATH and LD_LIBRARY_PATH
// set to library paths in the APK.
bool BuildEnvironmentWithApk(std::vector<std::string>* result) {
DCHECK(result->empty());
base::FilePath apk_path;
if (!base::android::GetPathToBaseApk(&apk_path)) {
return false;
}
std::unique_ptr<base::Environment> env(base::Environment::Create());
static constexpr char kClasspathVar[] = "CLASSPATH";
std::string classpath;
env->GetVar(kClasspathVar, &classpath);
classpath = apk_path.value() + ":" + classpath;
static constexpr char kLdLibraryPathVar[] = "LD_LIBRARY_PATH";
std::string library_path;
env->GetVar(kLdLibraryPathVar, &library_path);
library_path = apk_path.value() + "!/lib/" CURRENT_ABI ":" + library_path;
result->push_back("CLASSPATH=" + classpath);
result->push_back("LD_LIBRARY_PATH=" + library_path);
for (char** envp = environ; *envp != nullptr; ++envp) {
if ((strncmp(*envp, kClasspathVar, strlen(kClasspathVar)) == 0 &&
(*envp)[strlen(kClasspathVar)] == '=') ||
(strncmp(*envp, kLdLibraryPathVar, strlen(kLdLibraryPathVar)) == 0 &&
(*envp)[strlen(kLdLibraryPathVar)] == '=')) {
continue;
}
result->push_back(*envp);
}
return true;
}
const char kCrashpadJavaMain[] =
"org.chromium.components.crash.browser.CrashpadMain";
#endif // OS_ANDROID
bool BuildHandlerArgs(base::FilePath* database_path,
void BuildHandlerArgs(base::FilePath* database_path,
base::FilePath* metrics_path,
std::string* url,
std::map<std::string, std::string>* process_annotations,
......@@ -241,7 +304,6 @@ bool BuildHandlerArgs(base::FilePath* database_path,
// so that minidumps produced by Crashpad's generate_dump tool will
// contain these annotations.
arguments->push_back("--monitor-self-annotation=ptype=crashpad-handler");
return true;
}
bool GetHandlerPath(base::FilePath* exe_dir, base::FilePath* handler_path) {
......@@ -291,24 +353,18 @@ class HandlerStarter {
}
base::FilePath Initialize() {
base::FilePath exe_dir;
base::FilePath handler_path;
if (!GetHandlerPath(&exe_dir, &handler_path)) {
return base::FilePath();
}
if (!SetLdLibraryPath(exe_dir)) {
return base::FilePath();
}
base::FilePath database_path;
base::FilePath metrics_path;
std::string url;
std::map<std::string, std::string> process_annotations;
std::vector<std::string> arguments;
if (!BuildHandlerArgs(&database_path, &metrics_path, &url,
&process_annotations, &arguments)) {
return base::FilePath();
BuildHandlerArgs(&database_path, &metrics_path, &url, &process_annotations,
&arguments);
base::FilePath exe_dir;
base::FilePath handler_path;
if (!GetHandlerPath(&exe_dir, &handler_path)) {
return database_path;
}
if (crashpad::SetSanitizationInfo(&browser_sanitization_info_)) {
......@@ -316,6 +372,26 @@ class HandlerStarter {
&browser_sanitization_info_));
}
#if defined(OS_ANDROID)
if (!base::PathExists(handler_path)) {
use_java_handler_ = true;
std::vector<std::string> env;
if (!BuildEnvironmentWithApk(&env)) {
return database_path;
}
bool result = GetCrashpadClient().StartJavaHandlerAtCrash(
kCrashpadJavaMain, &env, database_path, metrics_path, url,
process_annotations, arguments);
DCHECK(result);
return database_path;
}
#endif
if (!SetLdLibraryPath(exe_dir)) {
return database_path;
}
bool result = GetCrashpadClient().StartHandlerAtCrash(
handler_path, database_path, metrics_path, url, process_annotations,
arguments);
......@@ -324,23 +400,35 @@ class HandlerStarter {
}
bool StartHandlerForClient(int fd) {
base::FilePath database_path;
base::FilePath metrics_path;
std::string url;
std::map<std::string, std::string> process_annotations;
std::vector<std::string> arguments;
BuildHandlerArgs(&database_path, &metrics_path, &url, &process_annotations,
&arguments);
base::FilePath exe_dir;
base::FilePath handler_path;
if (!GetHandlerPath(&exe_dir, &handler_path)) {
return false;
}
if (!SetLdLibraryPath(exe_dir)) {
return false;
#if defined(OS_ANDROID)
if (use_java_handler_) {
std::vector<std::string> env;
if (!BuildEnvironmentWithApk(&env)) {
return false;
}
bool result = GetCrashpadClient().StartJavaHandlerForClient(
kCrashpadJavaMain, &env, database_path, metrics_path, url,
process_annotations, arguments, fd);
return result;
}
#endif
base::FilePath database_path;
base::FilePath metrics_path;
std::string url;
std::map<std::string, std::string> process_annotations;
std::vector<std::string> arguments;
if (!BuildHandlerArgs(&database_path, &metrics_path, &url,
&process_annotations, &arguments)) {
if (!SetLdLibraryPath(exe_dir)) {
return false;
}
......@@ -354,6 +442,9 @@ class HandlerStarter {
~HandlerStarter() = delete;
crashpad::SanitizationInformation browser_sanitization_info_;
#if defined(OS_ANDROID)
bool use_java_handler_ = false;
#endif
DISALLOW_COPY_AND_ASSIGN(HandlerStarter);
};
......
......@@ -176,6 +176,7 @@ android_apk("content_shell_apk") {
"//media/capture/video/android:capture_java",
"//net/android:net_java",
"//services/shape_detection:shape_detection_java",
"//third_party/crashpad/crashpad/handler:crashpad_handler_named_as_so",
"//third_party/mesa_headers",
"//ui/android:ui_java",
]
......@@ -183,6 +184,7 @@ android_apk("content_shell_apk") {
android_manifest = content_shell_manifest
android_manifest_dep = ":content_shell_manifest"
shared_libraries = [ ":libcontent_shell_content_view" ]
loadable_modules = [ "$root_out_dir/libcrashpad_handler.so" ]
command_line_flags_file = "content-shell-command-line"
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment