зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1753758 - Add a crash method to ProcessToolsService r=gsvelto
Differential Revision: https://phabricator.services.mozilla.com/D137907
This commit is contained in:
Родитель
8170056817
Коммит
5b3f94efd9
|
@ -33,6 +33,14 @@ interface nsIProcessToolsService: nsISupports {
|
|||
*/
|
||||
void kill(in unsigned long long pid);
|
||||
|
||||
/**
|
||||
* Crash a process running on this system. Generates a SIGABRT on Linux and
|
||||
* macOS, and a STATUS_ILLEGAL_INSTRUCTION on Windows.
|
||||
*
|
||||
* Does cause a crash report to be generated.
|
||||
*/
|
||||
void crash(in unsigned long long pid);
|
||||
|
||||
/**
|
||||
* The pid for the current process.
|
||||
*/
|
||||
|
|
|
@ -25,6 +25,19 @@ pub unsafe extern "C" fn new_process_tools_service(result: *mut *const nsIProces
|
|||
RefPtr::new(service.coerce::<nsIProcessToolsService>()).forget(&mut *result);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::ffi::c_void;
|
||||
|
||||
// We want to generate an exception that can be caught by the exception handler
|
||||
// when injecting in a remote process, STATUS_ACCESS_VIOLATION seems not to do,
|
||||
// it but the following code generates a STATUS_ILLEGAL_INSTRUCTION that seems
|
||||
// to do the trick
|
||||
#[cfg(target_os = "windows")]
|
||||
pub unsafe extern "system" fn crash_illegal_instruction(_arg: *mut c_void) -> u32 {
|
||||
std::ptr::null_mut::<u32>().write(1);
|
||||
0
|
||||
}
|
||||
|
||||
// Implementation note:
|
||||
//
|
||||
// We're following the strategy employed by the `kvstore`.
|
||||
|
@ -87,6 +100,65 @@ impl ProcessToolsService {
|
|||
}
|
||||
}
|
||||
|
||||
// Method `crash`
|
||||
|
||||
xpcom_method!(
|
||||
crash => Crash(id: u64)
|
||||
);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn crash(&self, pid: u64) -> Result<(), nsresult> {
|
||||
let target_proc = unsafe {
|
||||
winapi::um::processthreadsapi::OpenProcess(
|
||||
/* dwDesiredAccess */
|
||||
winapi::um::winnt::PROCESS_VM_OPERATION
|
||||
| winapi::um::winnt::PROCESS_CREATE_THREAD
|
||||
| winapi::um::winnt::PROCESS_QUERY_INFORMATION,
|
||||
/* bInheritHandle */ 0,
|
||||
/* dwProcessId */ pid.try_into().unwrap(),
|
||||
)
|
||||
};
|
||||
if target_proc.is_null() {
|
||||
// Could not open process.
|
||||
return Err(NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
let new_thread = unsafe {
|
||||
winapi::um::processthreadsapi::CreateRemoteThread(
|
||||
/* hProcess */ target_proc,
|
||||
/* lpThreadAttributes */ std::ptr::null_mut(),
|
||||
/* dwStackSize */ 0,
|
||||
/* lpStartAddress */ Some(crash_illegal_instruction),
|
||||
/* lpParameter */ std::ptr::null_mut(),
|
||||
/* dwCreationFlags */ 0,
|
||||
/* lpThreadId */ std::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
|
||||
// Close handle regardless of success.
|
||||
let _ = unsafe {
|
||||
winapi::um::synchapi::WaitForSingleObject(new_thread, winapi::um::winbase::INFINITE);
|
||||
winapi::um::handleapi::CloseHandle(new_thread);
|
||||
winapi::um::handleapi::CloseHandle(target_proc);
|
||||
};
|
||||
|
||||
if new_thread.is_null() {
|
||||
return Err(NS_ERROR_FAILURE);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub fn crash(&self, pid: u64) -> Result<(), nsresult> {
|
||||
let pid = pid.try_into().or(Err(NS_ERROR_FAILURE))?;
|
||||
let result = unsafe { libc::kill(pid, libc::SIGABRT) };
|
||||
if result == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(NS_ERROR_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
// Attribute `pid`
|
||||
|
||||
xpcom_method!(
|
||||
|
|
Загрузка…
Ссылка в новой задаче