]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
su: Clean up PAM resources on all error paths
authorTobias Stoeckmann <tobias@stoeckmann.org>
Fri, 3 Apr 2026 07:40:24 +0000 (09:40 +0200)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 8 Apr 2026 10:14:03 +0000 (12:14 +0200)
In most cases, PAM resources are already cleaned up in error paths. Some
exceptions exist though.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
login-utils/login.c
login-utils/su-common.c

index b6d8aaf2ae24a5778adfba56e71961a02b1c0706..0f303e7534a66db05e896e40d3d44593ed9c361e 100644 (file)
@@ -1094,8 +1094,8 @@ static void loginpam_session(struct login_context *cxt)
 
        rc = pam_setcred(pamh, PAM_REINITIALIZE_CRED);
        if (is_pam_failure(rc)) {
-               pam_setcred(cxt->pamh, PAM_DELETE_CRED);
                pam_close_session(pamh, 0);
+               pam_setcred(cxt->pamh, PAM_DELETE_CRED);
                loginpam_err(pamh, rc);
        }
 }
index eb366678aa98c07a91859ea0c9c56b4a90771c0e..57651ea9ee33e4fc74fd8ba1c48e4fc24c7d727d 100644 (file)
@@ -407,8 +407,10 @@ static void supam_authenticate(struct su_context *su)
                 * This is the only difference between runuser(1) and su(1). The command
                 * runuser(1) does not required authentication, because user is root.
                 */
-               if (su->restricted)
+               if (su->restricted) {
+                       pam_end(su->pamh, PAM_ABORT);
                        errx(EXIT_FAILURE, _("may not be used by non-root users"));
+               }
                return;
        }
 
@@ -554,10 +556,14 @@ static void create_watching_parent(struct su_context *su)
                ul_pty_slave_echo(su->pty, 1);
 
                /* create pty */
-               if (ul_pty_setup(su->pty))
+               if (ul_pty_setup(su->pty)) {
+                       supam_cleanup(su, PAM_ABORT);
                        err(EXIT_FAILURE, _("failed to create pseudo-terminal"));
-               if (ul_pty_signals_setup(su->pty))
+               }
+               if (ul_pty_signals_setup(su->pty)) {
+                       supam_cleanup(su, PAM_ABORT);
                        err(EXIT_FAILURE, _("failed to initialize signals handler"));
+               }
        }
 #endif
        fflush(stdout);                 /* ??? */
@@ -760,9 +766,12 @@ static void init_groups(struct su_context *su, gid_t *groups, size_t ngroups)
        endgrent();
 
        rc = pam_setcred(su->pamh, PAM_ESTABLISH_CRED);
-       if (is_pam_failure(rc))
-               errx(EXIT_FAILURE, _("failed to establish user credentials: %s"),
-                                       pam_strerror(su->pamh, rc));
+       if (is_pam_failure(rc)) {
+               const char *msg = pam_strerror(su->pamh, rc);
+
+               supam_cleanup(su, rc);
+               errx(EXIT_FAILURE, _("failed to establish user credentials: %s"), msg);
+       }
        su->pam_has_cred = 1;
 }
 
@@ -1216,8 +1225,10 @@ int su_main(int argc, char **argv, int mode)
                ON_DBG(PTY, ul_pty_init_debug(0xffff));
 
                su->pty = ul_new_pty(su->isterm);
-               if (!su->pty)
+               if (!su->pty) {
+                       supam_cleanup(su, PAM_ABORT);
                        err(EXIT_FAILURE, _("failed to allocate pty handler"));
+               }
        }
 #endif
        create_watching_parent(su);