From 688dd7f2fddc8cf8c01dfadd05725497f0b9158c Mon Sep 17 00:00:00 2001 From: Pierre Warnier Date: Tue, 24 Mar 2026 12:33:11 +0100 Subject: [PATCH] security: add gshadow lock in useradd write_new_gshadow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/uu/useradd/src/useradd.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/uu/useradd/src/useradd.rs b/src/uu/useradd/src/useradd.rs index 8c26703..279eac5 100644 --- a/src/uu/useradd/src/useradd.rs +++ b/src/uu/useradd/src/useradd.rs @@ -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)?; } }