]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
passwd: Fix TOCTOU race condition (no PAM)
authorTobias Stoeckmann <tobias@stoeckmann.org>
Tue, 16 Dec 2025 13:00:54 +0000 (14:00 +0100)
committerAlejandro Colomar <foss+github@alejandro-colomar.es>
Tue, 16 Dec 2025 14:10:24 +0000 (15:10 +0100)
The passwd tool checks if the password of a user may be changed before
locking the passwd/shadow files. This leaves a time window to perform
the same action twice (e.g. circumventing PASS_MIN_DAYS limit) or to
circumvent a locked password by an administrator.

Perform the check after the lock again. This keeps the behavior as it
is today for a user and also prevents the race condition.

Reviewed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
src/passwd.c

index fe6ae66837c5fd9de75a7ee84748eb3235652976..17cda7745cbd7f8d539ed40b500632270853e12d 100644 (file)
@@ -649,6 +649,7 @@ static void update_noshadow(bool process_selinux)
                                Prog, name, pw_dbname ());
                fail_exit (E_NOPERM, process_selinux);
        }
+       check_password(pw, pwd_to_spwd(pw), process_selinux);
        npw = __pw_dup (pw);
        if (NULL == npw) {
                oom (process_selinux);
@@ -664,6 +665,7 @@ static void update_noshadow(bool process_selinux)
 
 static void update_shadow(bool process_selinux)
 {
+       const struct passwd pw = { .pw_passwd = SHADOW_PASSWD_STRING };
        const struct spwd *sp;
        struct spwd *nsp;
 
@@ -673,6 +675,7 @@ static void update_shadow(bool process_selinux)
                update_noshadow (process_selinux);
                return;
        }
+       check_password(&pw, sp, process_selinux);
        nsp = __spw_dup (sp);
        if (NULL == nsp) {
                oom (process_selinux);