1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-23 19:53:43 +00:00

Add rust module to prevent run-time memory dumping of main (#9393)

This commit is contained in:
Bernd Schoolmann
2024-08-05 21:51:38 +02:00
committed by GitHub
parent 2ea691e81c
commit 8090a89a32
11 changed files with 144 additions and 4 deletions

View File

@@ -496,6 +496,7 @@ dependencies = [
"core-foundation",
"gio",
"keytar",
"libc",
"libsecret",
"rand",
"retry",

View File

@@ -17,6 +17,7 @@ arboard = { version = "=3.4.0", default-features = false, features = [
] }
base64 = "=0.22.1"
cbc = { version = "=0.1.2", features = ["alloc"] }
libc = "0.2.155"
rand = "=0.8.5"
retry = "=2.0.0"
scopeguard = "=1.2.0"

View File

@@ -3,4 +3,5 @@ pub mod clipboard;
pub mod crypto;
pub mod error;
pub mod password;
pub mod process_isolation;
pub mod powermonitor;

View File

@@ -0,0 +1,51 @@
use anyhow::Result;
use libc::{c_int, self};
#[cfg(target_env = "gnu")]
use libc::c_uint;
// RLIMIT_CORE is the maximum size of a core dump file. Setting both to 0 disables core dumps, on crashes
// https://github.com/torvalds/linux/blob/1613e604df0cd359cf2a7fbd9be7a0bcfacfabd0/include/uapi/asm-generic/resource.h#L20
#[cfg(target_env = "musl")]
const RLIMIT_CORE: c_int = 4;
#[cfg(target_env = "gnu")]
const RLIMIT_CORE: c_uint = 4;
// PR_SET_DUMPABLE makes it so no other running process (root or same user) can dump the memory of this process
// or attach a debugger to it.
// https://github.com/torvalds/linux/blob/a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6/include/uapi/linux/prctl.h#L14
const PR_SET_DUMPABLE: c_int = 4;
pub fn disable_coredumps() -> Result<()> {
let rlimit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
if unsafe { libc::setrlimit(RLIMIT_CORE, &rlimit) } != 0 {
let e = std::io::Error::last_os_error();
return Err(anyhow::anyhow!("failed to disable core dumping, memory might be persisted to disk on crashes {}", e))
}
Ok(())
}
pub fn is_core_dumping_disabled() -> Result<bool> {
let mut rlimit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
if unsafe { libc::getrlimit(RLIMIT_CORE, &mut rlimit) } != 0 {
let e = std::io::Error::last_os_error();
return Err(anyhow::anyhow!("failed to get core dump limit {}", e))
}
Ok(rlimit.rlim_cur == 0 && rlimit.rlim_max == 0)
}
pub fn disable_memory_access() -> Result<()> {
if unsafe { libc::prctl(PR_SET_DUMPABLE, 0) } != 0 {
let e = std::io::Error::last_os_error();
return Err(anyhow::anyhow!("failed to disable memory dumping, memory is dumpable by other processes {}", e))
}
Ok(())
}

View File

@@ -0,0 +1,13 @@
use anyhow::{bail, Result};
pub fn disable_coredumps() -> Result<()> {
bail!("Not implemented on Mac")
}
pub fn is_core_dumping_disabled() -> Result<bool> {
bail!("Not implemented on Mac")
}
pub fn disable_memory_access() -> Result<()> {
bail!("Not implemented on Mac")
}

View File

@@ -0,0 +1,5 @@
#[cfg_attr(target_os = "linux", path = "linux.rs")]
#[cfg_attr(target_os = "windows", path = "windows.rs")]
#[cfg_attr(target_os = "macos", path = "macos.rs")]
mod process_isolation;
pub use process_isolation::*;

View File

@@ -0,0 +1,13 @@
use anyhow::{bail, Result};
pub fn disable_coredumps() -> Result<()> {
bail!("Not implemented on Windows")
}
pub fn is_core_dumping_disabled() -> Result<bool> {
bail!("Not implemented on Windows")
}
pub fn disable_memory_access() -> Result<()> {
bail!("Not implemented on Windows")
}

View File

@@ -41,6 +41,12 @@ export namespace clipboards {
export function read(): Promise<string>
export function write(text: string, password: boolean): Promise<void>
}
export namespace processisolations {
export function disableCoredumps(): Promise<void>
export function isCoreDumpingDisabled(): Promise<boolean>
export function disableMemoryAccess(): Promise<void>
}
export namespace powermonitors {
export function onLock(callback: (err: Error | null, ) => any): Promise<void>
export function isLockMonitorAvailable(): Promise<boolean>

View File

@@ -206,9 +206,10 @@ if (!nativeBinding) {
throw new Error(`Failed to load native binding`)
}
const { passwords, biometrics, clipboards, powermonitors } = nativeBinding
const { passwords, biometrics, clipboards, processisolations, powermonitors } = nativeBinding
module.exports.passwords = passwords
module.exports.biometrics = biometrics
module.exports.clipboards = clipboards
module.exports.processisolations = processisolations
module.exports.powermonitors = powermonitors

View File

@@ -142,6 +142,25 @@ pub mod clipboards {
}
}
#[napi]
pub mod processisolations {
#[napi]
pub async fn disable_coredumps() -> napi::Result<()> {
desktop_core::process_isolation::disable_coredumps()
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[napi]
pub async fn is_core_dumping_disabled() -> napi::Result<bool> {
desktop_core::process_isolation::is_core_dumping_disabled()
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[napi]
pub async fn disable_memory_access() -> napi::Result<()> {
desktop_core::process_isolation::disable_memory_access()
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
}
#[napi]
pub mod powermonitors {
use napi::{threadsafe_function::{ErrorStrategy::CalleeHandled, ThreadsafeFunction, ThreadsafeFunctionCallMode}, tokio};