Fix MAX_UNAUTH_CLIENTS regression

Since re-exec change in 2022.82 Dropbear count
treat authenticated sessions towards the unauthenticated
session limit. This is fixed by passing the childpipe FD
through to the re-execed process.
This commit is contained in:
Matt Johnston 2022-06-08 21:26:20 +08:00
parent f2318d831b
commit 544f28a051
3 changed files with 26 additions and 15 deletions

View File

@ -79,8 +79,9 @@ typedef struct svr_runopts {
char *addresses[DROPBEAR_MAX_PORTS]; char *addresses[DROPBEAR_MAX_PORTS];
int inetdmode; int inetdmode;
/* Hidden "-2" flag indicates it's re-executing itself */ /* Hidden "-2 childpipe_fd" flag indicates it's re-executing itself,
int reexec_child; stores the childpipe preauth file descriptor. Set to -1 otherwise. */
int reexec_childpipe;
/* Flags indicating whether to use ipv4 and ipv6 */ /* Flags indicating whether to use ipv4 and ipv6 */
/* not used yet /* not used yet

View File

@ -71,7 +71,7 @@ int main(int argc, char ** argv)
#endif #endif
#if DROPBEAR_DO_REEXEC #if DROPBEAR_DO_REEXEC
if (svr_opts.reexec_child) { if (svr_opts.reexec_childpipe >= 0) {
#ifdef PR_SET_NAME #ifdef PR_SET_NAME
/* Fix the "Name:" in /proc/pid/status, otherwise it's /* Fix the "Name:" in /proc/pid/status, otherwise it's
a FD number from fexecve. a FD number from fexecve.
@ -102,7 +102,7 @@ static void main_inetd() {
seedrandom(); seedrandom();
if (!svr_opts.reexec_child) { if (svr_opts.reexec_childpipe < 0) {
/* In case our inetd was lax in logging source addresses */ /* In case our inetd was lax in logging source addresses */
get_socket_address(0, NULL, NULL, &host, &port, 0); get_socket_address(0, NULL, NULL, &host, &port, 0);
dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port); dropbear_log(LOG_INFO, "Child connection from %s:%s", host, port);
@ -115,10 +115,8 @@ static void main_inetd() {
setsid(); setsid();
} }
/* Start service program /* -1 for childpipe in the inetd case is discarded */
* -1 is a dummy childpipe, just something we can close() without svr_session(0, svr_opts.reexec_childpipe);
* mattering. */
svr_session(0, -1);
/* notreached */ /* notreached */
} }
@ -347,9 +345,10 @@ static void main_noinetd(int argc, char ** argv, const char* multipath) {
if (execfd >= 0) { if (execfd >= 0) {
#if DROPBEAR_DO_REEXEC #if DROPBEAR_DO_REEXEC
/* Add "-2" to the args and re-execute ourself. */ /* Add "-2 childpipe[1]" to the args and re-execute ourself. */
char **new_argv = m_malloc(sizeof(char*) * (argc+3)); char **new_argv = m_malloc(sizeof(char*) * (argc+4));
int pos0 = 0, new_argc = argc+1; char buf[10];
int pos0 = 0, new_argc = argc+2;
/* We need to specially handle "dropbearmulti dropbear". */ /* We need to specially handle "dropbearmulti dropbear". */
if (multipath) { if (multipath) {
@ -359,7 +358,9 @@ static void main_noinetd(int argc, char ** argv, const char* multipath) {
} }
memcpy(&new_argv[pos0], argv, sizeof(char*) * argc); memcpy(&new_argv[pos0], argv, sizeof(char*) * argc);
new_argv[new_argc-1] = "-2"; new_argv[new_argc-2] = "-2";
snprintf(buf, sizeof(buf), "%d", childpipe[1]);
new_argv[new_argc-1] = buf;
new_argv[new_argc] = NULL; new_argv[new_argc] = NULL;
if ((dup2(childsock, STDIN_FILENO) < 0)) { if ((dup2(childsock, STDIN_FILENO) < 0)) {

View File

@ -138,6 +138,7 @@ void svr_getopts(int argc, char ** argv) {
char* keepalive_arg = NULL; char* keepalive_arg = NULL;
char* idle_timeout_arg = NULL; char* idle_timeout_arg = NULL;
char* maxauthtries_arg = NULL; char* maxauthtries_arg = NULL;
char* reexec_fd_arg = NULL;
char* keyfile = NULL; char* keyfile = NULL;
char c; char c;
#if DROPBEAR_PLUGIN #if DROPBEAR_PLUGIN
@ -175,6 +176,7 @@ void svr_getopts(int argc, char ** argv) {
svr_opts.pubkey_plugin_options = NULL; svr_opts.pubkey_plugin_options = NULL;
#endif #endif
svr_opts.pass_on_env = 0; svr_opts.pass_on_env = 0;
svr_opts.reexec_childpipe = -1;
#ifndef DISABLE_ZLIB #ifndef DISABLE_ZLIB
opts.compress_mode = DROPBEAR_COMPRESS_DELAYED; opts.compress_mode = DROPBEAR_COMPRESS_DELAYED;
@ -250,12 +252,12 @@ void svr_getopts(int argc, char ** argv) {
#if DROPBEAR_DO_REEXEC && NON_INETD_MODE #if DROPBEAR_DO_REEXEC && NON_INETD_MODE
/* For internal use by re-exec */ /* For internal use by re-exec */
case '2': case '2':
svr_opts.reexec_child = 1; next = &reexec_fd_arg;
break; break;
#endif #endif
case 'p': case 'p':
nextisport = 1; nextisport = 1;
break; break;
case 'P': case 'P':
next = &svr_opts.pidfile; next = &svr_opts.pidfile;
break; break;
@ -426,6 +428,13 @@ void svr_getopts(int argc, char ** argv) {
dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command); dropbear_log(LOG_INFO, "Forced command set to '%s'", svr_opts.forced_command);
} }
if (reexec_fd_arg) {
if (m_str_to_uint(reexec_fd_arg, &svr_opts.reexec_childpipe) == DROPBEAR_FAILURE
|| svr_opts.reexec_childpipe < 0) {
dropbear_exit("Bad -2");
}
}
#if INETD_MODE #if INETD_MODE
if (svr_opts.inetdmode && ( if (svr_opts.inetdmode && (
opts.usingsyslog == 0 opts.usingsyslog == 0