bmh10 / rpms / openssh

Forked from rpms/openssh 10 days ago
Clone
Dmitry Belyavskiy b82d68
diff --git a/channels.c b/channels.c
Dmitry Belyavskiy b82d68
index 32d1f617..0024f751 100644
Dmitry Belyavskiy b82d68
--- a/channels.c
Dmitry Belyavskiy b82d68
+++ b/channels.c
Dmitry Belyavskiy b82d68
@@ -333,7 +333,27 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
Dmitry Belyavskiy c3e6e4
 #endif
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy b82d68
 	/* enable nonblocking mode */
Dmitry Belyavskiy c3e6e4
-	if (nonblock) {
Dmitry Belyavskiy b82d68
+	c->restore_block = 0;
Dmitry Belyavskiy b82d68
+	if (nonblock == CHANNEL_NONBLOCK_STDIO) {
Dmitry Belyavskiy b82d68
+		/*
Dmitry Belyavskiy b82d68
+		 * Special handling for stdio file descriptors: do not set
Dmitry Belyavskiy b82d68
+		 * non-blocking mode if they are TTYs. Otherwise prepare to
Dmitry Belyavskiy b82d68
+		 * restore their blocking state on exit to avoid interfering
Dmitry Belyavskiy b82d68
+		 * with other programs that follow.
Dmitry Belyavskiy b82d68
+		 */
Dmitry Belyavskiy b82d68
+		if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) {
Dmitry Belyavskiy b82d68
+			c->restore_block |= CHANNEL_RESTORE_RFD;
Dmitry Belyavskiy b82d68
+			set_nonblock(rfd);
Dmitry Belyavskiy b82d68
+		}
Dmitry Belyavskiy b82d68
+		if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) {
Dmitry Belyavskiy b82d68
+			c->restore_block |= CHANNEL_RESTORE_WFD;
Dmitry Belyavskiy b82d68
+			set_nonblock(wfd);
Dmitry Belyavskiy b82d68
+		}
Dmitry Belyavskiy b82d68
+		if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) {
Dmitry Belyavskiy b82d68
+			c->restore_block |= CHANNEL_RESTORE_EFD;
Dmitry Belyavskiy b82d68
+			set_nonblock(efd);
Dmitry Belyavskiy b82d68
+		}
Dmitry Belyavskiy b82d68
+	} else if (nonblock) {
Dmitry Belyavskiy b82d68
 		if (rfd != -1)
Dmitry Belyavskiy b82d68
 			set_nonblock(rfd);
Dmitry Belyavskiy b82d68
 		if (wfd != -1)
Dmitry Belyavskiy b82d68
@@ -422,17 +442,23 @@ channel_find_maxfd(struct ssh_channels *sc)
Dmitry Belyavskiy c3e6e4
 }
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
 int
Dmitry Belyavskiy c3e6e4
-channel_close_fd(struct ssh *ssh, int *fdp)
Dmitry Belyavskiy b82d68
+channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
Dmitry Belyavskiy c3e6e4
 {
Dmitry Belyavskiy c3e6e4
 	struct ssh_channels *sc = ssh->chanctxt;
Dmitry Belyavskiy b82d68
-	int ret = 0, fd = *fdp;
Dmitry Belyavskiy b82d68
+	int ret, fd = *fdp;
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
-	if (fd != -1) {
Dmitry Belyavskiy b82d68
-		ret = close(fd);
Dmitry Belyavskiy b82d68
-		*fdp = -1;
Dmitry Belyavskiy b82d68
-		if (fd == sc->channel_max_fd)
Dmitry Belyavskiy b82d68
-			channel_find_maxfd(sc);
Dmitry Belyavskiy b82d68
-	}
Dmitry Belyavskiy b82d68
+	if (fd == -1)
Dmitry Belyavskiy b82d68
+		return 0;
Dmitry Belyavskiy b82d68
+
Dmitry Belyavskiy b82d68
+	if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) ||
Dmitry Belyavskiy b82d68
+	   (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) ||
Dmitry Belyavskiy b82d68
+	   (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0))
Dmitry Belyavskiy b82d68
+		(void)fcntl(*fdp, F_SETFL, 0);	/* restore blocking */
Dmitry Belyavskiy b82d68
+
Dmitry Belyavskiy b82d68
+	ret = close(fd);
Dmitry Belyavskiy b82d68
+	*fdp = -1;
Dmitry Belyavskiy b82d68
+	if (fd == sc->channel_max_fd)
Dmitry Belyavskiy b82d68
+		channel_find_maxfd(sc);
Dmitry Belyavskiy b82d68
 	return ret;
Dmitry Belyavskiy b82d68
 }
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
@@ -442,13 +468,13 @@ channel_close_fds(struct ssh *ssh, Channel *c)
Dmitry Belyavskiy c3e6e4
 {
Dmitry Belyavskiy c3e6e4
 	int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
-	channel_close_fd(ssh, &c->sock);
Dmitry Belyavskiy b82d68
+	channel_close_fd(ssh, c, &c->sock);
Dmitry Belyavskiy c3e6e4
 	if (rfd != sock)
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->rfd);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->rfd);
Dmitry Belyavskiy c3e6e4
 	if (wfd != sock && wfd != rfd)
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->wfd);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->wfd);
Dmitry Belyavskiy c3e6e4
 	if (efd != sock && efd != rfd && efd != wfd)
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->efd);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->efd);
Dmitry Belyavskiy c3e6e4
 }
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
 static void
Dmitry Belyavskiy b82d68
@@ -702,7 +728,7 @@ channel_stop_listening(struct ssh *ssh)
Dmitry Belyavskiy c3e6e4
 			case SSH_CHANNEL_X11_LISTENER:
Dmitry Belyavskiy c3e6e4
 			case SSH_CHANNEL_UNIX_LISTENER:
Dmitry Belyavskiy c3e6e4
 			case SSH_CHANNEL_RUNIX_LISTENER:
Dmitry Belyavskiy c3e6e4
-				channel_close_fd(ssh, &c->sock);
Dmitry Belyavskiy b82d68
+				channel_close_fd(ssh, c, &c->sock);
Dmitry Belyavskiy c3e6e4
 				channel_free(ssh, c);
Dmitry Belyavskiy c3e6e4
 				break;
Dmitry Belyavskiy c3e6e4
 			}
Dmitry Belyavskiy b82d68
@@ -1491,7 +1517,8 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 Channel *
Dmitry Belyavskiy b82d68
 channel_connect_stdio_fwd(struct ssh *ssh,
Dmitry Belyavskiy b82d68
-    const char *host_to_connect, u_short port_to_connect, int in, int out)
Dmitry Belyavskiy b82d68
+    const char *host_to_connect, u_short port_to_connect,
Dmitry Belyavskiy b82d68
+    int in, int out, int nonblock)
Dmitry Belyavskiy b82d68
 {
Dmitry Belyavskiy b82d68
 	Channel *c;
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
@@ -1499,7 +1526,7 @@ channel_connect_stdio_fwd(struct ssh *ssh,
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
Dmitry Belyavskiy b82d68
 	    -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
Dmitry Belyavskiy b82d68
-	    0, "stdio-forward", /*nonblock*/0);
Dmitry Belyavskiy b82d68
+	    0, "stdio-forward", nonblock);
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	c->path = xstrdup(host_to_connect);
Dmitry Belyavskiy b82d68
 	c->host_port = port_to_connect;
Dmitry Belyavskiy b82d68
@@ -1649,7 +1676,7 @@ channel_post_x11_listener(struct ssh *ssh, Channel *c,
Dmitry Belyavskiy c3e6e4
 	if (c->single_connection) {
Dmitry Belyavskiy c3e6e4
 		oerrno = errno;
Dmitry Belyavskiy c3e6e4
 		debug2("single_connection: closing X11 listener.");
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->sock);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->sock);
Dmitry Belyavskiy c3e6e4
 		chan_mark_dead(ssh, c);
Dmitry Belyavskiy c3e6e4
 		errno = oerrno;
Dmitry Belyavskiy c3e6e4
 	}
Dmitry Belyavskiy b82d68
@@ -2058,7 +2085,7 @@ channel_handle_efd_write(struct ssh *ssh, Channel *c,
Dmitry Belyavskiy c3e6e4
 		return 1;
Dmitry Belyavskiy c3e6e4
 	if (len <= 0) {
Dmitry Belyavskiy c3e6e4
 		debug2("channel %d: closing write-efd %d", c->self, c->efd);
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->efd);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->efd);
Dmitry Belyavskiy c3e6e4
 	} else {
Dmitry Belyavskiy c3e6e4
 		if ((r = sshbuf_consume(c->extended, len)) != 0)
Dmitry Belyavskiy c3e6e4
 			fatal_fr(r, "channel %i: consume", c->self);
Dmitry Belyavskiy b82d68
@@ -2087,7 +2114,7 @@ channel_handle_efd_read(struct ssh *ssh, Channel *c,
Dmitry Belyavskiy c3e6e4
 		return 1;
Dmitry Belyavskiy c3e6e4
 	if (len <= 0) {
Dmitry Belyavskiy c3e6e4
 		debug2("channel %d: closing read-efd %d", c->self, c->efd);
Dmitry Belyavskiy c3e6e4
-		channel_close_fd(ssh, &c->efd);
Dmitry Belyavskiy b82d68
+		channel_close_fd(ssh, c, &c->efd);
Dmitry Belyavskiy c3e6e4
 	} else if (c->extended_usage == CHAN_EXTENDED_IGNORE)
Dmitry Belyavskiy c3e6e4
 		debug3("channel %d: discard efd", c->self);
Dmitry Belyavskiy c3e6e4
 	else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
Dmitry Belyavskiy b82d68
diff --git a/channels.h b/channels.h
Dmitry Belyavskiy b82d68
index 378d987c..6bf86b00 100644
Dmitry Belyavskiy b82d68
--- a/channels.h
Dmitry Belyavskiy b82d68
+++ b/channels.h
Dmitry Belyavskiy b82d68
@@ -63,6 +63,16 @@
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy b82d68
 #define CHANNEL_CANCEL_PORT_STATIC	-1
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
+/* nonblocking flags for channel_new */
Dmitry Belyavskiy b82d68
+#define CHANNEL_NONBLOCK_LEAVE	0 /* don't modify non-blocking state */
Dmitry Belyavskiy b82d68
+#define CHANNEL_NONBLOCK_SET	1 /* set non-blocking state */
Dmitry Belyavskiy b82d68
+#define CHANNEL_NONBLOCK_STDIO	2 /* set non-blocking and restore on close */
Dmitry Belyavskiy b82d68
+
Dmitry Belyavskiy b82d68
+/* c->restore_block mask flags */
Dmitry Belyavskiy b82d68
+#define CHANNEL_RESTORE_RFD	0x01
Dmitry Belyavskiy b82d68
+#define CHANNEL_RESTORE_WFD	0x02
Dmitry Belyavskiy b82d68
+#define CHANNEL_RESTORE_EFD	0x04
Dmitry Belyavskiy c3e6e4
+
Dmitry Belyavskiy b82d68
 /* TCP forwarding */
Dmitry Belyavskiy b82d68
 #define FORWARD_DENY		0
Dmitry Belyavskiy b82d68
 #define FORWARD_REMOTE		(1)
Dmitry Belyavskiy b82d68
@@ -139,6 +149,7 @@ struct Channel {
Dmitry Belyavskiy b82d68
 				 * to a matching pre-select handler.
Dmitry Belyavskiy b82d68
 				 * this way post-select handlers are not
Dmitry Belyavskiy b82d68
 				 * accidentally called if a FD gets reused */
Dmitry Belyavskiy b82d68
+	int	restore_block;	/* fd mask to restore blocking status */
Dmitry Belyavskiy b82d68
 	struct sshbuf *input;	/* data read from socket, to be sent over
Dmitry Belyavskiy b82d68
 				 * encrypted connection */
Dmitry Belyavskiy b82d68
 	struct sshbuf *output;	/* data received over encrypted connection for
Dmitry Belyavskiy b82d68
@@ -266,7 +277,7 @@ void	 channel_register_filter(struct ssh *, int, channel_infilter_fn *,
Dmitry Belyavskiy c3e6e4
 void	 channel_register_status_confirm(struct ssh *, int,
Dmitry Belyavskiy c3e6e4
 	    channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
Dmitry Belyavskiy c3e6e4
 void	 channel_cancel_cleanup(struct ssh *, int);
Dmitry Belyavskiy c3e6e4
-int	 channel_close_fd(struct ssh *, int *);
Dmitry Belyavskiy b82d68
+int	 channel_close_fd(struct ssh *, Channel *, int *);
Dmitry Belyavskiy c3e6e4
 void	 channel_send_window_changes(struct ssh *);
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
 /* mux proxy support */
Dmitry Belyavskiy b82d68
@@ -313,7 +324,7 @@ Channel	*channel_connect_to_port(struct ssh *, const char *, u_short,
Dmitry Belyavskiy b82d68
 	    char *, char *, int *, const char **);
Dmitry Belyavskiy b82d68
 Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
Dmitry Belyavskiy b82d68
 Channel	*channel_connect_stdio_fwd(struct ssh *, const char*,
Dmitry Belyavskiy b82d68
-	    u_short, int, int);
Dmitry Belyavskiy b82d68
+	    u_short, int, int, int);
Dmitry Belyavskiy b82d68
 Channel	*channel_connect_by_listen_address(struct ssh *, const char *,
Dmitry Belyavskiy b82d68
 	    u_short, char *, char *);
Dmitry Belyavskiy b82d68
 Channel	*channel_connect_by_listen_path(struct ssh *, const char *,
Dmitry Belyavskiy b82d68
diff --git a/clientloop.c b/clientloop.c
Dmitry Belyavskiy b82d68
index 219f0e90..bdd67686 100644
Dmitry Belyavskiy b82d68
--- a/clientloop.c
Dmitry Belyavskiy b82d68
+++ b/clientloop.c
Dmitry Belyavskiy b82d68
@@ -1405,14 +1405,6 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
Dmitry Belyavskiy b82d68
 	if (have_pty)
Dmitry Belyavskiy b82d68
 		leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
-	/* restore blocking io */
Dmitry Belyavskiy b82d68
-	if (!isatty(fileno(stdin)))
Dmitry Belyavskiy b82d68
-		unset_nonblock(fileno(stdin));
Dmitry Belyavskiy b82d68
-	if (!isatty(fileno(stdout)))
Dmitry Belyavskiy b82d68
-		unset_nonblock(fileno(stdout));
Dmitry Belyavskiy b82d68
-	if (!isatty(fileno(stderr)))
Dmitry Belyavskiy b82d68
-		unset_nonblock(fileno(stderr));
Dmitry Belyavskiy b82d68
-
Dmitry Belyavskiy b82d68
 	/*
Dmitry Belyavskiy b82d68
 	 * If there was no shell or command requested, there will be no remote
Dmitry Belyavskiy b82d68
 	 * exit status to be returned.  In that case, clear error code if the
Dmitry Belyavskiy b82d68
diff --git a/mux.c b/mux.c
Dmitry Belyavskiy b82d68
index faf4ef1e..9454bfed 100644
Dmitry Belyavskiy b82d68
--- a/mux.c
Dmitry Belyavskiy b82d68
+++ b/mux.c
Dmitry Belyavskiy b82d68
@@ -452,14 +452,6 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
Dmitry Belyavskiy b82d68
 	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
Dmitry Belyavskiy b82d68
 		error_f("tcgetattr: %s", strerror(errno));
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
-	/* enable nonblocking unless tty */
Dmitry Belyavskiy b82d68
-	if (!isatty(new_fd[0]))
Dmitry Belyavskiy b82d68
-		set_nonblock(new_fd[0]);
Dmitry Belyavskiy b82d68
-	if (!isatty(new_fd[1]))
Dmitry Belyavskiy b82d68
-		set_nonblock(new_fd[1]);
Dmitry Belyavskiy b82d68
-	if (!isatty(new_fd[2]))
Dmitry Belyavskiy b82d68
-		set_nonblock(new_fd[2]);
Dmitry Belyavskiy b82d68
-
Dmitry Belyavskiy b82d68
 	window = CHAN_SES_WINDOW_DEFAULT;
Dmitry Belyavskiy b82d68
 	packetmax = CHAN_SES_PACKET_DEFAULT;
Dmitry Belyavskiy b82d68
 	if (cctx->want_tty) {
Dmitry Belyavskiy b82d68
@@ -469,7 +461,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
Dmitry Belyavskiy b82d68
 	    new_fd[0], new_fd[1], new_fd[2], window, packetmax,
Dmitry Belyavskiy b82d68
-	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
Dmitry Belyavskiy b82d68
+	    CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO);
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	nc->ctl_chan = c->self;		/* link session -> control channel */
Dmitry Belyavskiy b82d68
 	c->remote_id = nc->self;	/* link control -> session channel */
Dmitry Belyavskiy b82d68
@@ -1025,13 +1017,8 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
Dmitry Belyavskiy b82d68
 		}
Dmitry Belyavskiy b82d68
 	}
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
-	/* enable nonblocking unless tty */
Dmitry Belyavskiy b82d68
-	if (!isatty(new_fd[0]))
Dmitry Belyavskiy b82d68
-		set_nonblock(new_fd[0]);
Dmitry Belyavskiy b82d68
-	if (!isatty(new_fd[1]))
Dmitry Belyavskiy b82d68
-		set_nonblock(new_fd[1]);
Dmitry Belyavskiy b82d68
-
Dmitry Belyavskiy b82d68
-	nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
Dmitry Belyavskiy b82d68
+	nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1],
Dmitry Belyavskiy b82d68
+	    CHANNEL_NONBLOCK_STDIO);
Dmitry Belyavskiy b82d68
 	free(chost);
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	nc->ctl_chan = c->self;		/* link session -> control channel */
Dmitry Belyavskiy b82d68
diff --git a/nchan.c b/nchan.c
Dmitry Belyavskiy b82d68
index 4a4494b8..7ef3a350 100644
Dmitry Belyavskiy b82d68
--- a/nchan.c
Dmitry Belyavskiy b82d68
+++ b/nchan.c
Dmitry Belyavskiy b82d68
@@ -384,7 +384,7 @@ chan_shutdown_write(struct ssh *ssh, Channel *c)
Dmitry Belyavskiy c3e6e4
 			    c->istate, c->ostate, strerror(errno));
Dmitry Belyavskiy c3e6e4
 		}
Dmitry Belyavskiy c3e6e4
 	} else {
Dmitry Belyavskiy c3e6e4
-		if (channel_close_fd(ssh, &c->wfd) < 0) {
Dmitry Belyavskiy b82d68
+		if (channel_close_fd(ssh, c, &c->wfd) < 0) {
Dmitry Belyavskiy c3e6e4
 			logit_f("channel %d: close() failed for "
Dmitry Belyavskiy c3e6e4
 			    "fd %d [i%d o%d]: %.100s", c->self, c->wfd,
Dmitry Belyavskiy c3e6e4
 			    c->istate, c->ostate, strerror(errno));
Dmitry Belyavskiy b82d68
@@ -412,7 +412,7 @@ chan_shutdown_read(struct ssh *ssh, Channel *c)
Dmitry Belyavskiy c3e6e4
 			    c->istate, c->ostate, strerror(errno));
Dmitry Belyavskiy c3e6e4
 		}
Dmitry Belyavskiy c3e6e4
 	} else {
Dmitry Belyavskiy c3e6e4
-		if (channel_close_fd(ssh, &c->rfd) < 0) {
Dmitry Belyavskiy b82d68
+		if (channel_close_fd(ssh, c, &c->rfd) < 0) {
Dmitry Belyavskiy c3e6e4
 			logit_f("channel %d: close() failed for "
Dmitry Belyavskiy c3e6e4
 			    "fd %d [i%d o%d]: %.100s", c->self, c->rfd,
Dmitry Belyavskiy c3e6e4
 			    c->istate, c->ostate, strerror(errno));
Dmitry Belyavskiy b82d68
@@ -431,7 +431,7 @@ chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
Dmitry Belyavskiy c3e6e4
 	debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
Dmitry Belyavskiy c3e6e4
 	    c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
Dmitry Belyavskiy c3e6e4
 	    channel_format_extended_usage(c));
Dmitry Belyavskiy c3e6e4
-	if (channel_close_fd(ssh, &c->efd) < 0) {
Dmitry Belyavskiy b82d68
+	if (channel_close_fd(ssh, c, &c->efd) < 0) {
Dmitry Belyavskiy c3e6e4
 		logit_f("channel %d: close() failed for "
Dmitry Belyavskiy c3e6e4
 		    "extended fd %d [i%d o%d]: %.100s", c->self, c->efd,
Dmitry Belyavskiy c3e6e4
 		    c->istate, c->ostate, strerror(errno));
Dmitry Belyavskiy b82d68
diff --git a/ssh.c b/ssh.c
Dmitry Belyavskiy b82d68
index 696dc3bc..6243db76 100644
Dmitry Belyavskiy b82d68
--- a/ssh.c
Dmitry Belyavskiy b82d68
+++ b/ssh.c
Dmitry Belyavskiy b82d68
@@ -1876,9 +1876,10 @@ ssh_init_stdio_forwarding(struct ssh *ssh)
Dmitry Belyavskiy b82d68
 
Dmitry Belyavskiy b82d68
 	if ((in = dup(STDIN_FILENO)) == -1 ||
Dmitry Belyavskiy b82d68
 	    (out = dup(STDOUT_FILENO)) == -1)
Dmitry Belyavskiy b82d68
-		fatal("channel_connect_stdio_fwd: dup() in/out failed");
Dmitry Belyavskiy b82d68
+		fatal_f("dup() in/out failed");
Dmitry Belyavskiy b82d68
 	if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
Dmitry Belyavskiy b82d68
-	    options.stdio_forward_port, in, out)) == NULL)
Dmitry Belyavskiy b82d68
+	    options.stdio_forward_port, in, out,
Dmitry Belyavskiy b82d68
+	    CHANNEL_NONBLOCK_STDIO)) == NULL)
Dmitry Belyavskiy b82d68
 		fatal_f("channel_connect_stdio_fwd failed");
Dmitry Belyavskiy b82d68
 	channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
Dmitry Belyavskiy b82d68
 	channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
Dmitry Belyavskiy b82d68
@@ -2074,14 +2075,6 @@ ssh_session2_open(struct ssh *ssh)
Dmitry Belyavskiy c3e6e4
 	if (in == -1 || out == -1 || err == -1)
Dmitry Belyavskiy c3e6e4
 		fatal("dup() in/out/err failed");
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
-	/* enable nonblocking unless tty */
Dmitry Belyavskiy c3e6e4
-	if (!isatty(in))
Dmitry Belyavskiy c3e6e4
-		set_nonblock(in);
Dmitry Belyavskiy c3e6e4
-	if (!isatty(out))
Dmitry Belyavskiy c3e6e4
-		set_nonblock(out);
Dmitry Belyavskiy c3e6e4
-	if (!isatty(err))
Dmitry Belyavskiy c3e6e4
-		set_nonblock(err);
Dmitry Belyavskiy c3e6e4
-
Dmitry Belyavskiy c3e6e4
 	window = CHAN_SES_WINDOW_DEFAULT;
Dmitry Belyavskiy c3e6e4
 	packetmax = CHAN_SES_PACKET_DEFAULT;
Dmitry Belyavskiy c3e6e4
 	if (tty_flag) {
Dmitry Belyavskiy b82d68
@@ -2091,7 +2084,7 @@ ssh_session2_open(struct ssh *ssh)
Dmitry Belyavskiy c3e6e4
 	c = channel_new(ssh,
Dmitry Belyavskiy c3e6e4
 	    "session", SSH_CHANNEL_OPENING, in, out, err,
Dmitry Belyavskiy c3e6e4
 	    window, packetmax, CHAN_EXTENDED_WRITE,
Dmitry Belyavskiy c3e6e4
-	    "client-session", /*nonblock*/0);
Dmitry Belyavskiy b82d68
+	    "client-session", CHANNEL_NONBLOCK_STDIO);
Dmitry Belyavskiy c3e6e4
 
Dmitry Belyavskiy c3e6e4
 	debug3_f("channel_new: %d", c->self);
Dmitry Belyavskiy c3e6e4