Panic handler that passes info to crash reporter via memfds.

Crashes of rust executables have a generic signature since the user
crash collector is not able to compute a reasonable signature for them.
This custom panic hook allows passing a signature derived from PanicInfo
to the crash collector.

BUG=b:234093439
TEST=See crrev.com/c/3834930 and crrev.com/c/3836804

Change-Id: Ida7f655d3a2463e8a42602d8e32588195a0ce36b
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3842808
Commit-Queue: Paramjit Oberoi <psoberoi@google.com>
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: Paramjit Oberoi <psoberoi@google.com>
This commit is contained in:
Paramjit Oberoi 2022-08-11 16:56:21 -07:00 committed by crosvm LUCI
parent 1e16dc6a8f
commit 91113e63af
2 changed files with 35 additions and 0 deletions

View file

@ -30,6 +30,7 @@ mod mmap;
pub mod net;
mod netlink;
mod notifiers;
pub mod panic_handler;
pub mod platform_timer_resolution;
mod poll;
mod priority;

View file

@ -0,0 +1,34 @@
// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! A panic handler for better crash signatures for rust apps.
use super::SharedMemory;
use std::ffi::CString;
use std::io;
use std::mem;
use std::panic;
const PANIC_MEMFD_NAME: &str = "RUST_PANIC_SIG";
/// Inserts a panic handler that writes the panic info to a memfd called
/// "RUST_PANIC_SIG" before calling the original panic handler. This
/// makes it possible for external crash handlers to recover the panic info.
pub fn install_memfd_handler() {
let hook = panic::take_hook();
panic::set_hook(Box::new(move |p| {
let panic_info = format!("{}\n", &p);
let panic_bytes = panic_info.as_bytes();
// On failure, ignore the error and call the original handler.
if let Ok(mut panic_memfd) = SharedMemory::new(
&CString::new(PANIC_MEMFD_NAME).unwrap(),
panic_bytes.len() as u64,
) {
io::Write::write_all(&mut panic_memfd, panic_bytes).ok();
// Intentionally leak panic_memfd so it is picked up by the crash handler.
mem::forget(panic_memfd);
}
hook(p)
}));
}