From 8fd720c3e319da773b48c0b191f049dbd1e3c7f0 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Mon, 11 Jul 2016 23:09:33 +0800 Subject: [PATCH] Improve exit message formatting CVE: CVE-2016-7406 Upstream-Status: Backport [backported from: https://secure.ucc.asn.au/hg/dropbear/rev/b66a483f3dcb] Signed-off-by: Sona Sarmadi diff -ruN a/cli-main.c b/cli-main.c --- a/cli-main.c 2016-03-09 15:54:53.000000000 +0100 +++ b/cli-main.c 2016-10-20 12:49:00.323501119 +0200 @@ -85,29 +85,30 @@ #endif /* DBMULTI stuff */ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) { + char exitmsg[150]; + char fullmsg[300]; - char fmtbuf[300]; - char exitmsg[500]; + /* Note that exit message must be rendered before session cleanup */ + /* Render the formatted exit message */ + vsnprintf(exitmsg, sizeof(exitmsg), format, param); + + /* Add the prefix depending on session/auth state */ if (!sessinitdone) { - snprintf(fmtbuf, sizeof(fmtbuf), "Exited: %s", - format); + snprintf(fullmsg, sizeof(fullmsg), "Exited: %s", exitmsg); } else { - snprintf(fmtbuf, sizeof(fmtbuf), + snprintf(fullmsg, sizeof(fullmsg), "Connection to %s@%s:%s exited: %s", cli_opts.username, cli_opts.remotehost, - cli_opts.remoteport, format); + cli_opts.remoteport, exitmsg); } - /* Arguments to the exit printout may be unsafe to use after session_cleanup() */ - vsnprintf(exitmsg, sizeof(exitmsg), fmtbuf, param); - /* Do the cleanup first, since then the terminal will be reset */ session_cleanup(); /* Avoid printing onwards from terminal cruft */ fprintf(stderr, "\n"); - dropbear_log(LOG_INFO, "%s", exitmsg);; + dropbear_log(LOG_INFO, "%s", fullmsg); exit(exitcode); } diff -ruN a/svr-session.c b/svr-session.c --- a/svr-session.c 2016-03-09 15:54:54.000000000 +0100 +++ b/svr-session.c 2016-10-20 13:27:20.629628336 +0200 @@ -145,30 +145,33 @@ /* failure exit - format must be <= 100 chars */ void svr_dropbear_exit(int exitcode, const char* format, va_list param) { - char fmtbuf[300]; + char exitmsg[150]; + char fullmsg[300]; int i; + /* Render the formatted exit message */ + vsnprintf(exitmsg, sizeof(exitmsg), format, param); + + /* Add the prefix depending on session/auth state */ if (!sessinitdone) { /* before session init */ - snprintf(fmtbuf, sizeof(fmtbuf), - "Early exit: %s", format); + snprintf(fullmsg, sizeof(fullmsg), "Early exit: %s", exitmsg); } else if (ses.authstate.authdone) { /* user has authenticated */ - snprintf(fmtbuf, sizeof(fmtbuf), + snprintf(fullmsg, sizeof(fullmsg), "Exit (%s): %s", - ses.authstate.pw_name, format); + ses.authstate.pw_name, exitmsg); } else if (ses.authstate.pw_name) { /* we have a potential user */ - snprintf(fmtbuf, sizeof(fmtbuf), + snprintf(fullmsg, sizeof(fullmsg), "Exit before auth (user '%s', %d fails): %s", - ses.authstate.pw_name, ses.authstate.failcount, format); + ses.authstate.pw_name, ses.authstate.failcount, exitmsg); } else { /* before userauth */ - snprintf(fmtbuf, sizeof(fmtbuf), - "Exit before auth: %s", format); + snprintf(fullmsg, sizeof(fullmsg), "Exit before auth: %s", exitmsg); } - _dropbear_log(LOG_INFO, fmtbuf, param); + dropbear_log(LOG_INFO, "%s", fullmsg); #ifdef USE_VFORK /* For uclinux only the main server process should cleanup - we don't want