summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2023-08-18 01:37:41 +0000
committerDamien Miller <djm@mindrot.org>2023-08-18 12:04:05 +1000
commitf3e39c4700d543945ea89eedf4c8e8671d41200e (patch)
tree88b654ffc7bd389cbfed37d4dcec345b9541c415
parentc8e79e4872e1863438acd0204e2b8f05352575f9 (diff)
upstream: fix regression in OpenSSH 9.4 (mux.c r1.99) that caused
multiplexed sessions to ignore SIGINT under some circumstances. Reported by / feedback naddy@, ok dtucker@ OpenBSD-Commit-ID: 4d5c6c894664f50149153fd4764f21f43e7d7e5a
-rw-r--r--kex.c4
-rw-r--r--misc.c42
-rw-r--r--misc.h5
-rw-r--r--mux.c6
4 files changed, 39 insertions, 18 deletions
diff --git a/kex.c b/kex.c
index b4e2ab75..fd04bb0b 100644
--- a/kex.c
+++ b/kex.c
@@ -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.
*
@@ -1334,7 +1334,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.");
diff --git a/misc.c b/misc.c
index 4b87c409..95658703 100644
--- a/misc.c
+++ b/misc.c
@@ -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.
@@ -313,20 +313,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;
@@ -346,8 +364,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);
}
/*
@@ -381,7 +399,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 */
diff --git a/misc.h b/misc.h
index fd77a7fd..f9bdc6eb 100644
--- a/misc.h
+++ b/misc.h
@@ -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 *);
diff --git a/mux.c b/mux.c
index 3a0f8767..d9d5e7d9 100644
--- a/mux.c
+++ b/mux.c
@@ -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>
*
@@ -1480,7 +1480,9 @@ mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms)
case EWOULDBLOCK:
#endif
case EAGAIN:
- if (waitrfd(fd, &timeout_ms) == -1)
+ if (waitrfd(fd, &timeout_ms,
+ &muxclient_terminate) == -1 &&
+ errno != EINTR)
return -1; /* timeout */
/* FALLTHROUGH */
case EINTR: