]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: Fix mistracking of MaxStartups process exits in some
authordjm@openbsd.org <djm@openbsd.org>
Fri, 4 Jul 2025 09:51:01 +0000 (09:51 +0000)
committerDamien Miller <djm@mindrot.org>
Wed, 9 Jul 2025 20:19:05 +0000 (06:19 +1000)
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

diff --git a/sshd.c b/sshd.c
index b8345fca0fba70e863ef0d3aad0263933c75dd3a..6960193816f5c566b63845c07e9dc6b9a48470f9 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.620 2025/07/04 07:47:35 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.621 2025/07/04 09:51:01 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  * Copyright (c) 2002 Niels Provos.  All rights reserved.
@@ -293,8 +293,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);
@@ -315,6 +317,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;
        }
@@ -1043,7 +1046,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;
                        }
@@ -1082,23 +1084,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 */
@@ -1118,6 +1116,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;
                        }