fix: audit fix — reduce password copies in memory (v0.8.4)
- attempt_login takes Zeroizing<String> by value, eliminating the redundant Zeroizing::new(password.to_string()) that doubled the Rust-owned copy. - Clear password_entry's internal buffer immediately after extracting the password, shortening the window during which the GTK GString persists in non-zeroizable libc memory.
This commit is contained in:
parent
48d363bb18
commit
35f1a17cdf
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -575,7 +575,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "moongreet"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"gdk-pixbuf",
|
||||
"gdk4",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "moongreet"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
edition = "2024"
|
||||
description = "A greetd greeter for Wayland with GTK4 and Layer Shell"
|
||||
license = "MIT"
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
# Decisions
|
||||
|
||||
## 2026-04-24 – Audit fix: shrink password-in-memory window (v0.8.4)
|
||||
|
||||
- **Who**: ClaudeCode, Dom
|
||||
- **Why**: Security audit flagged the GTK password path as holding more copies of the plaintext password in memory than necessary. `attempt_login` wrapped the already-`Zeroizing<String>` caller value into a second `Zeroizing<String>` (`password.to_string()`), and the GTK `GString` backing `entry.text()` persisted in libc malloc'd memory until the allocator reused the page.
|
||||
- **Tradeoffs**: The GTK `GString` and the libc `strdup` copy on the PAM FFI boundary remain non-zeroizable — this is an inherent GTK/libc limitation, already documented in CLAUDE.md. This change reduces the Rust-owned copies to one and clears the `PasswordEntry` text field immediately after extraction to shorten the GTK-side window.
|
||||
- **How**: (1) `attempt_login` now takes `password: Zeroizing<String>` by value instead of `&str`, moving ownership into the `spawn_blocking` closure. (2) The redundant `Zeroizing::new(password.to_string())` inside `attempt_login` is removed. (3) `password_entry.set_text("")` is called right after the password is extracted from the activate handler, shortening the lifetime of the GTK-internal buffer.
|
||||
|
||||
## 2026-04-21 – Ship polkit rule in moongreet instead of moonarch (v0.8.3)
|
||||
|
||||
- **Who**: ClaudeCode, Dom
|
||||
|
||||
@ -493,6 +493,10 @@ pub fn create_greeter_window(
|
||||
let Some(user) = user else { return };
|
||||
|
||||
let password = Zeroizing::new(entry.text().to_string());
|
||||
// Clear the GTK entry's internal buffer as early as possible. GTK allocates
|
||||
// the backing `GString` via libc malloc, which `zeroize` cannot reach — the
|
||||
// best we can do is shorten the window during which it resides in memory.
|
||||
entry.set_text("");
|
||||
|
||||
let session = get_selected_session(&session_dropdown, &sessions_rc);
|
||||
let Some(session) = session else {
|
||||
@ -502,7 +506,7 @@ pub fn create_greeter_window(
|
||||
|
||||
attempt_login(
|
||||
&user,
|
||||
&password,
|
||||
password,
|
||||
&session,
|
||||
strings,
|
||||
&state,
|
||||
@ -953,7 +957,7 @@ fn set_login_sensitive(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn attempt_login(
|
||||
user: &User,
|
||||
password: &str,
|
||||
password: Zeroizing<String>,
|
||||
session: &Session,
|
||||
strings: &'static Strings,
|
||||
state: &Rc<RefCell<GreeterState>>,
|
||||
@ -992,7 +996,6 @@ fn attempt_login(
|
||||
set_login_sensitive(password_entry, session_dropdown, false);
|
||||
|
||||
let username = user.username.clone();
|
||||
let password = Zeroizing::new(password.to_string());
|
||||
let exec_cmd = session.exec_cmd.clone();
|
||||
let session_name = session.name.clone();
|
||||
let greetd_sock = state.borrow().greetd_sock.clone();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user