mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
Implement libmemory_security
This commit is contained in:
1
apps/desktop/.gitignore
vendored
1
apps/desktop/.gitignore
vendored
@@ -3,3 +3,4 @@ dist-safari/
|
||||
*.env
|
||||
PlugIns/safari.appex/
|
||||
xcuserdata/
|
||||
memory_security/target/
|
||||
48
apps/desktop/memory_security/Cargo.lock
generated
Normal file
48
apps/desktop/memory_security/Cargo.lock
generated
Normal 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",
|
||||
]
|
||||
11
apps/desktop/memory_security/Cargo.toml
Normal file
11
apps/desktop/memory_security/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "memory-security"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ctor = "0.5.0"
|
||||
libc = "0.2.175"
|
||||
39
apps/desktop/memory_security/src/isolate.rs
Normal file
39
apps/desktop/memory_security/src/isolate.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
#[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
|
||||
);
|
||||
}
|
||||
}
|
||||
42
apps/desktop/memory_security/src/lib.rs
Normal file
42
apps/desktop/memory_security/src/lib.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
//! 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 {
|
||||
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("MEMORY_SECURITY_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() {
|
||||
unsafe {
|
||||
println!("[memory-security] Enabling memory security for process {}", pid);
|
||||
isolate::disable_memory_access();
|
||||
isolate::disable_coredumps();
|
||||
}
|
||||
}
|
||||
@@ -46,4 +46,6 @@ modules:
|
||||
commands:
|
||||
- ulimit -c 0
|
||||
- export TMPDIR="$XDG_RUNTIME_DIR/app/$FLATPAK_ID"
|
||||
- export ZYPAK_LD_PRELOAD="/app/bin/libmemory_security.so"
|
||||
- export MEMORY_SECURITY_LD_PRELOAD="/app/bin/libmemory_security.so"
|
||||
- exec zypak-wrapper /app/bin/bitwarden-app "$@"
|
||||
|
||||
@@ -7,12 +7,19 @@ ulimit -c 0
|
||||
RAW_PATH=$(readlink -f "$0")
|
||||
APP_PATH=$(dirname $RAW_PATH)
|
||||
|
||||
# force use of base image libdus in snap
|
||||
if [ -e "/usr/lib/x86_64-linux-gnu/libdbus-1.so.3" ]
|
||||
then
|
||||
# force use of base image libdbus in snap
|
||||
if [ -e "/usr/lib/x86_64-linux-gnu/libdbus-1.so.3" ]; then
|
||||
export LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libdbus-1.so.3"
|
||||
fi
|
||||
|
||||
# If running in non-snap, add libmemory_security.so from app path to LD_PRELOAD
|
||||
# This prevents debugger / memory dumping on all desktop processes
|
||||
if [ -z "$SNAP" ] && [ -f "$APP_PATH/libmemory_security.so" ]; then
|
||||
LIBMEMORY_SECURITY_SO="$APP_PATH/libmemory_security.so"
|
||||
LD_PRELOAD="$LIBMEMORY_SECURITY_SO${LD_PRELOAD:+:$LD_PRELOAD}"
|
||||
export LD_PRELOAD
|
||||
fi
|
||||
|
||||
PARAMS="--enable-features=UseOzonePlatform,WaylandWindowDecorations --ozone-platform-hint=auto"
|
||||
if [ "$USE_X11" = "true" ]; then
|
||||
PARAMS=""
|
||||
|
||||
@@ -30,6 +30,17 @@ async function run(context) {
|
||||
fse.copyFileSync(wrapperScript, wrapperBin);
|
||||
fse.chmodSync(wrapperBin, "755");
|
||||
console.log("Copied memory-protection wrapper script");
|
||||
|
||||
const memorySecurityPath = path.join(__dirname, "../memory_security/");
|
||||
const memorySecurityLibPath = path.join(
|
||||
memorySecurityPath,
|
||||
"target",
|
||||
"release",
|
||||
"libmemory_security.so",
|
||||
);
|
||||
const memorySecurityLibOutPath = path.join(appOutDir, "libmemory_security.so");
|
||||
child_process.execSync(`cargo build --release`, { cwd: memorySecurityPath });
|
||||
fse.copyFileSync(memorySecurityLibPath, memorySecurityLibOutPath);
|
||||
}
|
||||
|
||||
if (["darwin", "mas"].includes(context.electronPlatformName)) {
|
||||
|
||||
Reference in New Issue
Block a user