https://github.com/openssh/openssh-portable/commit/78af391990b210ae0797c37c30719232cda61fef From 78af391990b210ae0797c37c30719232cda61fef Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Fri, 4 Jul 2025 09:51:01 +0000 Subject: [PATCH] upstream: Fix mistracking of MaxStartups process exits in some situations. At worst, this can cause all MaxStartups slots to fill and sshd to refuse new connections. Diagnosis by xnor; ok dtucker@ OpenBSD-Commit-ID: 10273033055552557196730f898ed6308b36a78d --- sshd.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/sshd.c b/sshd.c index 4a93e29e4c0..d721a5de36a 100644 --- a/sshd.c +++ b/sshd.c @@ -289,8 +289,10 @@ child_finish(struct early_child *child) { if (children_active == 0) fatal_f("internal error: children_active underflow"); - if (child->pipefd != -1) + if (child->pipefd != -1) { + srclimit_done(child->pipefd); close(child->pipefd); + } sshbuf_free(child->config); sshbuf_free(child->keys); free(child->id); @@ -311,6 +313,7 @@ child_close(struct early_child *child, int force_final, int quiet) if (!quiet) debug_f("enter%s", force_final ? " (forcing)" : ""); if (child->pipefd != -1) { + srclimit_done(child->pipefd); close(child->pipefd); child->pipefd = -1; } @@ -1039,7 +1042,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, if (ret <= 0) { if (children[i].early) listening--; - srclimit_done(children[i].pipefd); child_close(&(children[i]), 0, 0); continue; } @@ -1078,23 +1080,19 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, } /* FALLTHROUGH */ case 0: - /* child exited preauth */ + /* child closed pipe */ if (children[i].early) listening--; - srclimit_done(children[i].pipefd); + debug3_f("child %lu for %s closed pipe", + (long)children[i].pid, children[i].id); child_close(&(children[i]), 0, 0); break; case 1: if (children[i].config) { error_f("startup pipe %d (fd=%d)" - " early read", i, children[i].pipefd); - if (children[i].early) - listening--; - if (children[i].pid > 0) - kill(children[i].pid, SIGTERM); - srclimit_done(children[i].pipefd); - child_close(&(children[i]), 0, 0); - break; + " early read", + i, children[i].pipefd); + goto problem_child; } if (children[i].early && c == '\0') { /* child has finished preliminaries */ @@ -1114,6 +1112,12 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, "child %ld for %s in state %d", (int)c, (long)children[i].pid, children[i].id, children[i].early); + problem_child: + if (children[i].early) + listening--; + if (children[i].pid > 0) + kill(children[i].pid, SIGTERM); + child_close(&(children[i]), 0, 0); } break; }