From 24c33dbd17d8d764e836b83b0825a9c0e3f59c99 Mon Sep 17 00:00:00 2001 From: H-TTTTT <36735327+H-TTTTT@users.noreply.github.com> Date: Mon, 20 Jul 2026 09:41:19 +0800 Subject: [PATCH] fix: accept any execute bit for USE_SENDMAIL command check Operator precedence made `!mode & 0o111 != 0` require all three execute bits (u/g/o), so owner-only (0700) and group-executable (0750) sendmail commands were rejected as non-executable. Check `(mode & 0o111) != 0` via mode_is_executable and add a unit test for the common permission modes. Fixes #7445 --- src/config.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 49281b6c..0046e56d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -920,6 +920,28 @@ make_config! { }, } +#[cfg(unix)] +fn mode_is_executable(mode: u32) -> bool { + mode & 0o111 != 0 +} + +#[cfg(all(test, unix))] +mod tests { + use super::mode_is_executable; + + #[test] + fn executable_mode_accepts_any_execute_bit() { + assert!(mode_is_executable(0o100)); + assert!(mode_is_executable(0o010)); + assert!(mode_is_executable(0o001)); + assert!(mode_is_executable(0o700)); + assert!(mode_is_executable(0o750)); + assert!(mode_is_executable(0o755)); + assert!(!mode_is_executable(0o600)); + assert!(!mode_is_executable(0o000)); + } +} + fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> { // Validate connection URL is valid and DB feature is enabled #[cfg(sqlite)] @@ -1136,7 +1158,7 @@ fn validate_config(cfg: &ConfigItems, on_update: bool) -> Result<(), Error> { #[cfg(unix)] { use std::os::unix::fs::PermissionsExt; - if !metadata.permissions().mode() & 0o111 != 0 { + if !mode_is_executable(metadata.permissions().mode()) { err!(format!("sendmail command at `{path:?}` isn't executable")); } }