fix: audit fixes — power timeout, timing mitigation, release profile, GREETD_SOCK cache (v0.7.1)
Update PKGBUILD version / update-pkgver (push) Successful in 2s

- Add 30s timeout with SIGKILL to power actions (adapted from moonset)
- Add 500ms minimum login response time against timing enumeration
- Cache GREETD_SOCK in GreeterState at startup
- Add [profile.release] with LTO, codegen-units=1, strip
- Add compressed="true" to GResource CSS/SVG entries
- Add SYNC comments to duplicated blur/background functions
- Add nix dependency for signal handling in power timeout
This commit is contained in:
2026-03-31 11:08:40 +02:00
parent 60d294fa37
commit f6f33a13ab
6 changed files with 125 additions and 26 deletions
+19 -3
View File
@@ -133,6 +133,10 @@ pub fn load_background_texture(bg_path: &Path) -> Option<gdk::Texture> {
// -- GPU blur via GskBlurNode -------------------------------------------------
// SYNC: MAX_BLUR_DIMENSION, render_blurred_texture, and create_background_picture
// are duplicated in moonlock/src/lockscreen.rs and moonset/src/panel.rs.
// Changes here must be mirrored to the other two projects.
/// Maximum texture dimension before downscaling for blur.
/// Keeps GPU work reasonable on 4K+ displays.
const MAX_BLUR_DIMENSION: f32 = 1920.0;
@@ -240,6 +244,7 @@ struct GreeterState {
default_avatar_texture: Option<gdk::Texture>,
failed_attempts: HashMap<String, u32>,
greetd_sock: Arc<Mutex<Option<UnixStream>>>,
greetd_sock_path: Option<String>,
login_cancelled: Arc<std::sync::atomic::AtomicBool>,
fingerprint_available: bool,
/// Incremented on each user switch to discard stale async results.
@@ -281,12 +286,16 @@ pub fn create_greeter_window(
log::debug!("GTK theme: {theme}");
}
// Cache GREETD_SOCK at startup — it never changes during runtime
let greetd_sock_path = std::env::var("GREETD_SOCK").ok().filter(|p| !p.is_empty());
let state = Rc::new(RefCell::new(GreeterState {
selected_user: None,
avatar_cache: HashMap::new(),
default_avatar_texture: None,
failed_attempts: HashMap::new(),
greetd_sock: Arc::new(Mutex::new(None)),
greetd_sock_path,
login_cancelled: Arc::new(std::sync::atomic::AtomicBool::new(false)),
fingerprint_available: false,
user_switch_generation: 0,
@@ -960,9 +969,9 @@ fn attempt_login(
session_dropdown: &gtk::DropDown,
) {
log::debug!("Login attempt for user: {}", user.username);
let sock_path = match std::env::var("GREETD_SOCK") {
Ok(p) if !p.is_empty() => p,
_ => {
let sock_path = match state.borrow().greetd_sock_path.clone() {
Some(p) => p,
None => {
show_error(error_label, password_entry, strings.greetd_sock_not_set);
return;
}
@@ -1009,6 +1018,8 @@ fn attempt_login(
state,
async move {
let session_name_clone = session_name.clone();
// Minimum response time to prevent username enumeration via timing
let login_start = std::time::Instant::now();
let result = gio::spawn_blocking(move || {
login_worker(
&username,
@@ -1022,6 +1033,11 @@ fn attempt_login(
)
})
.await;
let elapsed = login_start.elapsed();
let min_response = std::time::Duration::from_millis(500);
if elapsed < min_response {
glib::timeout_future(min_response - elapsed).await;
}
match result {
Ok(Ok(LoginResult::Success { username })) => {