diff --git a/apps/desktop/memory_security/src/isolate.rs b/apps/desktop/memory_security/src/isolate.rs index 521e681f3ce..7d97aa6b09b 100644 --- a/apps/desktop/memory_security/src/isolate.rs +++ b/apps/desktop/memory_security/src/isolate.rs @@ -15,7 +15,7 @@ const RLIMIT_CORE: c_uint = 4; const PR_SET_DUMPABLE: c_int = 4; /// Prevents a process crash from creating a coredump on disk -pub(crate) fn disable_coredumps() -> () { +pub(crate) fn disable_coredumps() { let rlimit = libc::rlimit { rlim_cur: 0, rlim_max: 0, @@ -23,17 +23,14 @@ pub(crate) fn disable_coredumps() -> () { 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); + eprintln!("[Process Isolation] Failed to disable core dumping: {e}"); } } /// Prevents other process from accessing env, memory, attaching debugger -pub(crate) fn isolate_process() -> () { +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 - ); + eprintln!("[Process Isolation] Failed to disable memory dumping: {e}"); } } diff --git a/apps/desktop/memory_security/src/lib.rs b/apps/desktop/memory_security/src/lib.rs index 78e724a0f10..9c23a3cb1c7 100644 --- a/apps/desktop/memory_security/src/lib.rs +++ b/apps/desktop/memory_security/src/lib.rs @@ -17,26 +17,29 @@ unsafe extern "C" { /// 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())); + 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("MEMORY_SECURITY_LD_PRELOAD").unwrap_or_default(); - std::env::set_var("LD_PRELOAD", ld_preload); - return 0; + 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) } - - original_unsetenv(name) } // Hooks the shared object being loaded into the process #[ctor::ctor] fn preload_init() { + let pid = unsafe { libc::getpid() }; unsafe { - println!("[memory-security] Enabling memory security for process {}", pid); - isolate::disable_memory_access(); + println!("[memory-security] Enabling memory security for process {pid}"); + isolate::isolate_process(); isolate::disable_coredumps(); } } diff --git a/apps/desktop/memory_security/test_isolation.sh b/apps/desktop/memory_security/test_isolation.sh new file mode 100644 index 00000000000..4464a3c865f --- /dev/null +++ b/apps/desktop/memory_security/test_isolation.sh @@ -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 \ No newline at end of file diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 42eb7017e03..87a37a4450a 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -34,9 +34,10 @@ "build:renderer:watch": "cross-env NODE_ENV=development webpack --config webpack.renderer.js --watch", "electron": "node ./scripts/start.js", "electron:ignore": "node ./scripts/start.js --ignore-certificate-errors", + "flatpak:dev": "npm run clean:dist && electron-builder --dir -p never && flatpak-builder --force-clean --install --user ../../.flatpak/ ./resources/com.bitwarden.desktop.devel.yaml && flatpak run com.bitwarden.desktop", "clean:dist": "rimraf ./dist", "pack:dir": "npm run clean:dist && electron-builder --dir -p never", - "pack:lin:flatpak": "npm run clean:dist && electron-builder --dir -p never && flatpak-builder --repo=build/.repo build/.flatpak ./resources/com.bitwarden.desktop.devel.yaml --install-deps-from=flathub --force-clean && flatpak build-bundle ./build/.repo/ ./dist/com.bitwarden.desktop.flatpak com.bitwarden.desktop", + "pack:lin:flatpak": "npm run clean:dist && electron-builder --dir -p never && flatpak-builder --repo=../../.flatpak-repo ../../.flatpak ./resources/com.bitwarden.desktop.devel.yaml --install-deps-from=flathub --force-clean && flatpak build-bundle ../../.flatpak-repo/ ./dist/com.bitwarden.desktop.flatpak com.bitwarden.desktop", "pack:lin": "npm run clean:dist && electron-builder --linux --x64 -p never && export SNAP_FILE=$(realpath ./dist/bitwarden_*.snap) && unsquashfs -d ./dist/tmp-snap/ $SNAP_FILE && mkdir -p ./dist/tmp-snap/meta/polkit/ && cp ./resources/com.bitwarden.desktop.policy ./dist/tmp-snap/meta/polkit/polkit.com.bitwarden.desktop.policy && rm $SNAP_FILE && snap pack --compression=lzo ./dist/tmp-snap/ && mv ./*.snap ./dist/ && rm -rf ./dist/tmp-snap/", "pack:lin:arm64": "npm run clean:dist && electron-builder --dir -p never && tar -czvf ./dist/bitwarden_desktop_arm64.tar.gz -C ./dist/linux-arm64-unpacked/ .", "pack:mac": "npm run clean:dist && electron-builder --mac --universal -p never",