From: Todd C. Miller Date: Mon, 21 Sep 2015 21:07:00 +0000 (-0600) Subject: Fix potential double free of the cookie when sudo is suspended at X-Git-Tag: SUDO_1_8_15^2~44 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0cfce655bd04b020eb1bd48c47f4439bb27bbd6f;p=sudo Fix potential double free of the cookie when sudo is suspended at the password prompt. --- 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); }