From 0cfce655bd04b020eb1bd48c47f4439bb27bbd6f Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 21 Sep 2015 15:07:00 -0600 Subject: [PATCH] Fix potential double free of the cookie when sudo is suspended at the password prompt. --- plugins/sudoers/check.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c index c37d4bb5f..0aa9e0357 100644 --- a/plugins/sudoers/check.c +++ b/plugins/sudoers/check.c @@ -89,19 +89,23 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw) { struct sudo_conv_callback cb, *callback = NULL; struct getpass_closure closure; - void *cookie = NULL; int status = TS_ERROR; int rval = -1; char *prompt; bool lectured; debug_decl(check_user_interactive, SUDOERS_DEBUG_AUTH) + /* Setup closure for getpass_{suspend,resume} */ + closure.auth_pw = auth_pw; + closure.cookie = NULL; + sudo_pw_addref(closure.auth_pw); + /* Open, lock and read time stamp file if we are using it. */ if (!ISSET(mode, MODE_IGNORE_TICKET)) { /* Open time stamp file and check its status. */ - cookie = timestamp_open(user_name, user_sid); - if (timestamp_lock(cookie, auth_pw)) - status = timestamp_status(cookie, auth_pw); + closure.cookie = timestamp_open(user_name, user_sid); + if (timestamp_lock(closure.cookie, closure.auth_pw)) + status = timestamp_status(closure.cookie, closure.auth_pw); /* Construct callback for getpass function. */ memset(&cb, 0, sizeof(cb)); @@ -110,10 +114,6 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw) cb.on_suspend = getpass_suspend; cb.on_resume = getpass_resume; callback = &cb; - - /* Closure for getpass_{suspend,resume} */ - closure.auth_pw = auth_pw; - closure.cookie = cookie; } switch (status) { @@ -142,11 +142,11 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw) /* Expand any escapes in the prompt. */ prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, - auth_pw->pw_name); + closure.auth_pw->pw_name); if (prompt == NULL) goto done; - rval = verify_user(auth_pw, prompt, validated, callback); + rval = verify_user(closure.auth_pw, prompt, validated, callback); if (rval == true && lectured) (void)set_lectured(); /* lecture error not fatal */ free(prompt); @@ -158,10 +158,12 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw) * Failure to update the time stamp is not a fatal error. */ if (rval == true && ISSET(validated, VALIDATE_SUCCESS) && status != TS_ERROR) - (void)timestamp_update(cookie, auth_pw); + (void)timestamp_update(closure.cookie, closure.auth_pw); done: - if (cookie != NULL) - timestamp_close(cookie); + if (closure.cookie != NULL) + timestamp_close(closure.cookie); + sudo_pw_delref(closure.auth_pw); + debug_return_int(rval); } -- 2.40.0