1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-21 18:53:29 +00:00

Rename to process isolation

This commit is contained in:
Bernd Schoolmann
2025-08-24 16:03:37 +02:00
parent 44d6062f84
commit d434fd9b5d
9 changed files with 14 additions and 14 deletions

View File

@@ -0,0 +1,48 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ctor"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb"
dependencies = [
"ctor-proc-macro",
"dtor",
]
[[package]]
name = "ctor-proc-macro"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2"
[[package]]
name = "dtor"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934"
dependencies = [
"dtor-proc-macro",
]
[[package]]
name = "dtor-proc-macro"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5"
[[package]]
name = "libc"
version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "memory-security"
version = "0.1.0"
dependencies = [
"ctor",
"libc",
]

View File

@@ -0,0 +1,11 @@
[package]
name = "process-isolation"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
ctor = "0.5.0"
libc = "0.2.175"

View File

@@ -0,0 +1,36 @@
#[cfg(target_env = "gnu")]
use libc::c_uint;
use libc::{self, c_int};
/// 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;
/// Prevents a process crash from creating a coredump on disk
pub(crate) fn disable_coredumps() {
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();
eprintln!("[Process Isolation] Failed to disable core dumping: {e}");
}
}
/// Prevents other process from accessing env, memory, attaching debugger
pub(crate) fn isolate_process() {
if unsafe { libc::prctl(PR_SET_DUMPABLE, 0) } != 0 {
let e = std::io::Error::last_os_error();
eprintln!("[Process Isolation] Failed to disable memory dumping: {e}");
}
}

View File

@@ -0,0 +1,45 @@
//! This library compiles to a pre-loadable shared object. When preloaded, it
//! immediately isolates the process using the methods available on the platform.
//! On Linux, this is PR_SET_DUMPABLE to prevent debuggers from attaching, the env
//! from being read and the memory from being stolen.
use std::ffi::{c_char, c_void};
mod isolate;
#[link(name = "dl")]
unsafe extern "C" {
unsafe fn dlsym(handle: *const c_void, symbol: *const c_char) -> *const c_void;
}
/// Hooks unsetenv to fix a bug in zypak-wrapper.
/// Zypak unsets the env in Flatpak as a side-effect, which means that only the top level
/// processes would be hooked. With this work-around all processes in the tree are hooked
#[unsafe(no_mangle)]
unsafe extern "C" fn unsetenv(name: *const c_char) -> i32 {
unsafe {
let name_str = std::ffi::CStr::from_ptr(name).to_str().unwrap();
let original_unsetenv: unsafe extern "C" fn(*const c_char) -> i32 =
std::mem::transmute(dlsym(libc::RTLD_NEXT, c"unsetenv".as_ptr()));
if name_str == "LD_PRELOAD" {
// This env variable is provided by the flatpak configuration
let ld_preload = std::env::var("PROCESS_ISOLATION_LD_PRELOAD").unwrap_or_default();
std::env::set_var("LD_PRELOAD", ld_preload);
return 0;
}
original_unsetenv(name)
}
}
// Hooks the shared object being loaded into the process
#[ctor::ctor]
fn preload_init() {
let pid = unsafe { libc::getpid() };
unsafe {
println!("[Process Isolation] Enabling memory security for process {pid}");
isolate::isolate_process();
isolate::disable_coredumps();
}
}

View File

@@ -0,0 +1,40 @@
#!/bin/bash
# This script tests the memory isolation status of bitwarden-desktop processes. The script will print "isolated"
# if the memory is not accessible by other processes.
CURRENT_USER=$(whoami)
# Find processes with "bitwarden" in the command
pids=$(pgrep -f bitwarden)
if [[ -z "$pids" ]]; then
echo "No bitwarden processes found."
exit 0
fi
for pid in $pids; do
# Get process info: command, PPID, RSS memory
read cmd ppid rss <<<$(ps -o comm=,ppid=,rss= -p "$pid")
# Explicitly skip if the command line does not contain "bitwarden"
if ! grep -q "bitwarden" <<<"$cmd"; then
continue
fi
# Check ownership of /proc/$pid/environ
owner=$(stat -c "%U" /proc/$pid/environ 2>/dev/null)
if [[ "$owner" == "root" ]]; then
status="isolated"
elif [[ "$owner" == "$CURRENT_USER" ]]; then
status="insecure"
else
status="unknown-owner:$owner"
fi
# Convert memory to MB
mem_mb=$((rss / 1024))
echo "PID: $pid | CMD: $cmd | Mem: ${mem_mb}MB | Owner: $owner | Status: $status"
done