security: add gshadow lock in useradd write_new_gshadow

Fixes #75 — found by Codex (GPT-5.4) and Copilot.

write_new_gshadow now acquires FileLock on gshadow_path before
atomic_write. Prevents concurrent groupmod/useradd from silently
overwriting each other's gshadow changes.
This commit is contained in:
Pierre Warnier
2026-03-24 12:33:11 +01:00
parent 4c92f922c4
commit 688dd7f2fd
+5 -1
View File
@@ -524,10 +524,14 @@ fn do_useradd(opts: &UseraddOptions) -> UResult<()> {
// (matching GNU behavior). Locks are held throughout.
// -------------------------------------------------------------------
// Step 11: Create user group if needed (lock already held).
// Step 11: Create user group if needed (group lock already held).
if let Some(ref new_grp) = new_group {
write_new_group(&group_path, &mut group_entries, new_grp)?;
if gshadow_path.exists() {
// Acquire gshadow lock — group.lock does NOT protect gshadow.
let _gs_lock = FileLock::acquire(&gshadow_path).map_err(|e| {
UseraddError::CannotUpdateGroup(format!("cannot lock gshadow: {e}"))
})?;
write_new_gshadow(&gshadow_path, &mut gshadow_entries, new_grp)?;
}
}