fix(linux): recognize a login screen whose greeter uses another nologin path (#16675)

* fix(linux): recognize a login screen whose greeter uses another nologin path

is_prelogin() reads the active user's passwd entry and treats /bin/false or /usr/sbin/nologin as a greeter account. Greeter accounts on Arch use /usr/bin/nologin (gdm, sddm and lightdm) and others /sbin/nologin, so there a login screen was not detected: the audio service kept retrying the _pa ipc every second, which #16390 stopped at a login screen, and file transfer used the greeter's name. Match any nologin path.

* fix(linux): match nologin only in the shell field of the passwd entry

Checking the whole getent line also matched a home directory such as /home/nologin-test. Read the last field of each line and require it to end in /false or /nologin. Output with several lines, as getent prints for an empty name, still counts if any entry has such a shell, as before.

* fix(linux): compare the greeter shell with the known paths only

Match the shell field against /bin/false, /usr/bin/false, /usr/sbin/nologin, /sbin/nologin and /usr/bin/nologin instead of any path that ends in /false or /nologin, so a custom shell elsewhere is not taken for a login screen.
This commit is contained in:
Lukas authored and GitHub committed 2026-10-23 18:09:08 +08:00
1 parent 01e1323e51
commit 21c488b6ce
1 file changed
+11 -1
+11 -1
View File
@@ -1424,7 +1424,17 @@ pub fn is_prelogin() -> bool {
}
let name = get_active_username();
if let Ok(res) = run_cmds(&format!("getent passwd {}", name)) {
return res.contains("/bin/false") || res.contains("/usr/sbin/nologin");
return res.lines().any(|entry| {
let shell = entry.trim().rsplit(':').next().unwrap_or_default();
matches!(
shell,
"/bin/false"
| "/usr/bin/false"
| "/usr/sbin/nologin"
| "/sbin/nologin"
| "/usr/bin/nologin"
)
});
}
false
}