fix: audit MEDIUM fixes — D-Bus race, TOCTOU, FP reset, entry clear (v0.6.11)
- fingerprint: split cleanup_dbus into a sync take_cleanup_proxy() + async perform_dbus_cleanup(). resume_async now awaits VerifyStop+Release before re-claiming, so fprintd cannot reject the Claim on a slow bus. stop() still spawns the cleanup fire-and-forget. - fingerprint: remove failed_attempts = 0 from resume_async. An attacker with sensor control could otherwise cycle verify-match → account-fail → resume and never trip the 10-attempt cap. - lockscreen: open the wallpaper with O_NOFOLLOW and build the texture from bytes, closing the TOCTOU between the symlink check and Texture:: from_file. - lockscreen: clear password_entry immediately after extracting the Zeroizing<String>, shortening the window the GLib GString copy stays in libc-malloc'd memory.
This commit is contained in:
+30
-3
@@ -244,6 +244,10 @@ pub fn create_lockscreen_window(
|
||||
if password.is_empty() {
|
||||
return;
|
||||
}
|
||||
// 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("");
|
||||
|
||||
entry.set_sensitive(false);
|
||||
let username = username.clone();
|
||||
@@ -518,12 +522,35 @@ pub fn start_fingerprint(
|
||||
/// Load the wallpaper as a texture once, for sharing across all windows.
|
||||
/// Returns None if no wallpaper path is provided or the file cannot be loaded.
|
||||
/// Blur is applied at render time via GPU (GskBlurNode), not here.
|
||||
///
|
||||
/// Opens the file with O_NOFOLLOW to close the TOCTOU window between the
|
||||
/// symlink check in `resolve_background_path_with` and this read. If the path
|
||||
/// was swapped for a symlink after the check, `open` fails with ELOOP.
|
||||
pub fn load_background_texture(bg_path: &Path) -> Option<gdk::Texture> {
|
||||
let file = gio::File::for_path(bg_path);
|
||||
match gdk::Texture::from_file(&file) {
|
||||
use std::io::Read;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
let mut file = match std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.custom_flags(libc::O_NOFOLLOW)
|
||||
.open(bg_path)
|
||||
{
|
||||
Ok(f) => f,
|
||||
Err(e) => {
|
||||
log::warn!("Failed to open wallpaper {}: {e}", bg_path.display());
|
||||
return None;
|
||||
}
|
||||
};
|
||||
let mut bytes = Vec::new();
|
||||
if let Err(e) = file.read_to_end(&mut bytes) {
|
||||
log::warn!("Failed to read wallpaper {}: {e}", bg_path.display());
|
||||
return None;
|
||||
}
|
||||
let glib_bytes = glib::Bytes::from_owned(bytes);
|
||||
match gdk::Texture::from_bytes(&glib_bytes) {
|
||||
Ok(texture) => Some(texture),
|
||||
Err(e) => {
|
||||
log::warn!("Failed to load wallpaper {}: {e}", bg_path.display());
|
||||
log::warn!("Failed to decode wallpaper {}: {e}", bg_path.display());
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user