fix regression in OpenSSH 9.4 (mux.c r1.99) that caused multiplexed
authordjm <djm@openbsd.org>
Fri, 18 Aug 2023 01:37:41 +0000 (01:37 +0000)
committerdjm <djm@openbsd.org>
Fri, 18 Aug 2023 01:37:41 +0000 (01:37 +0000)
sessions to ignore SIGINT under some circumstances. Reported by /
feedback naddy@, ok dtucker@

usr.bin/ssh/kex.c
usr.bin/ssh/misc.c
usr.bin/ssh/misc.h
usr.bin/ssh/mux.c

index 3b08e34..cdd5c25 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.178 2023/03/12 10:40:39 dtucker Exp $ */
+/* $OpenBSD: kex.c,v 1.179 2023/08/18 01:37:41 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -1317,7 +1317,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
                for (;;) {
                        if (timeout_ms > 0) {
                                r = waitrfd(ssh_packet_get_connection_in(ssh),
-                                   &timeout_ms);
+                                   &timeout_ms, NULL);
                                if (r == -1 && errno == ETIMEDOUT) {
                                        send_error(ssh, "Timed out waiting "
                                            "for SSH identification string.");
index c49aa60..52d79e7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.185 2023/08/04 06:32:40 dtucker Exp $ */
+/* $OpenBSD: misc.c,v 1.186 2023/08/18 01:37:41 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005-2020 Damien Miller.  All rights reserved.
@@ -269,20 +269,38 @@ set_sock_tos(int fd, int tos)
  * Returns 0 if fd ready or -1 on timeout or error (see errno).
  */
 static int
-waitfd(int fd, int *timeoutp, short events)
+waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop)
 {
        struct pollfd pfd;
-       struct timeval t_start;
-       int oerrno, r, have_timeout = (*timeoutp >= 0);
+       struct timespec timeout;
+       int oerrno, r;
+       sigset_t nsigset, osigset;
 
+       if (timeoutp && *timeoutp == -1)
+               timeoutp = NULL;
        pfd.fd = fd;
        pfd.events = events;
-       for (; !have_timeout || *timeoutp >= 0;) {
-               monotime_tv(&t_start);
-               r = poll(&pfd, 1, *timeoutp);
+       ptimeout_init(&timeout);
+       if (timeoutp != NULL)
+               ptimeout_deadline_ms(&timeout, *timeoutp);
+       if (stop != NULL)
+               sigfillset(&nsigset);
+       for (; timeoutp == NULL || *timeoutp >= 0;) {
+               if (stop != NULL) {
+                       sigprocmask(SIG_BLOCK, &nsigset, &osigset);
+                       if (*stop) {
+                               sigprocmask(SIG_SETMASK, &osigset, NULL);
+                               errno = EINTR;
+                               return -1;
+                       }
+               }
+               r = ppoll(&pfd, 1, ptimeout_get_tsp(&timeout),
+                   stop != NULL ? &osigset : NULL);
                oerrno = errno;
-               if (have_timeout)
-                       ms_subtract_diff(&t_start, timeoutp);
+               if (stop != NULL)
+                       sigprocmask(SIG_SETMASK, &osigset, NULL);
+               if (timeoutp)
+                       *timeoutp = ptimeout_get_ms(&timeout);
                errno = oerrno;
                if (r > 0)
                        return 0;
@@ -302,8 +320,8 @@ waitfd(int fd, int *timeoutp, short events)
  * Returns 0 if fd ready or -1 on timeout or error (see errno).
  */
 int
-waitrfd(int fd, int *timeoutp) {
-       return waitfd(fd, timeoutp, POLLIN);
+waitrfd(int fd, int *timeoutp, volatile sig_atomic_t *stop) {
+       return waitfd(fd, timeoutp, POLLIN, stop);
 }
 
 /*
@@ -337,7 +355,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
                break;
        }
 
-       if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1)
+       if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT, NULL) == -1)
                return -1;
 
        /* Completed or failed */
index 9408223..0221ce2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.103 2023/07/19 14:02:27 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.104 2023/08/18 01:37:41 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <stdio.h>
+#include <signal.h>
 
 /* Data structure for representing a forwarding request. */
 struct Forward {
@@ -57,7 +58,7 @@ char  *get_rdomain(int);
 int     set_rdomain(int, const char *);
 int     get_sock_af(int);
 void    set_sock_tos(int, int);
-int     waitrfd(int, int *);
+int     waitrfd(int, int *, volatile sig_atomic_t *);
 int     timeout_connect(int, const struct sockaddr *, socklen_t, int *);
 int     a2port(const char *);
 int     a2tun(const char *, int *);
index 20ec1b0..df9be75 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.99 2023/08/04 06:32:40 dtucker Exp $ */
+/* $OpenBSD: mux.c,v 1.100 2023/08/18 01:37:41 djm Exp $ */
 /*
  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
  *
@@ -1464,7 +1464,9 @@ mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms)
                if (len == -1) {
                        switch (errno) {
                        case EAGAIN:
-                               if (waitrfd(fd, &timeout_ms) == -1)
+                               if (waitrfd(fd, &timeout_ms,
+                                   &muxclient_terminate) == -1 &&
+                                   errno != EINTR)
                                        return -1;      /* timeout */
                                /* FALLTHROUGH */
                        case EINTR: