summaryrefslogtreecommitdiff
path: root/nchan.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-10-04 07:47:35 +0000
committerDamien Miller <djm@mindrot.org>2018-10-04 17:50:22 +1000
commite0d6501e86734c48c8c503f81e1c0926e98c5c4c (patch)
tree94ba740e9fa6cc8ea015aa1ea49e63addc345301 /nchan.c
parent6f1aabb128246f445e33b8844fad3de9cb1d18cb (diff)
upstream: when the peer sends a channel-close message, make sure we
close the local extended read fd (stderr) along with the regular read fd (stdout). Avoids weird stuck processed in multiplexing mode. Report and analysis by Nelson Elhage and Geoffrey Thomas in bz#2863 ok dtucker@ markus@ OpenBSD-Commit-ID: a48a2467fe938de4de69d2e7193d5fa701f12ae9
Diffstat (limited to 'nchan.c')
-rw-r--r--nchan.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/nchan.c b/nchan.c
index da7a9d6d6..8294d7fca 100644
--- a/nchan.c
+++ b/nchan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: nchan.c,v 1.68 2018/10/04 00:10:11 djm Exp $ */ 1/* $OpenBSD: nchan.c,v 1.69 2018/10/04 07:47:35 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
4 * 4 *
@@ -80,6 +80,7 @@ static void chan_send_eow2(struct ssh *, Channel *);
80/* helper */ 80/* helper */
81static void chan_shutdown_write(struct ssh *, Channel *); 81static void chan_shutdown_write(struct ssh *, Channel *);
82static void chan_shutdown_read(struct ssh *, Channel *); 82static void chan_shutdown_read(struct ssh *, Channel *);
83static void chan_shutdown_extended_read(struct ssh *, Channel *);
83 84
84static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; 85static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
85static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; 86static const char *istates[] = { "open", "drain", "wait_oclose", "closed" };
@@ -289,11 +290,13 @@ chan_rcvd_oclose(struct ssh *ssh, Channel *c)
289 switch (c->istate) { 290 switch (c->istate) {
290 case CHAN_INPUT_OPEN: 291 case CHAN_INPUT_OPEN:
291 chan_shutdown_read(ssh, c); 292 chan_shutdown_read(ssh, c);
293 chan_shutdown_extended_read(ssh, c);
292 chan_set_istate(c, CHAN_INPUT_CLOSED); 294 chan_set_istate(c, CHAN_INPUT_CLOSED);
293 break; 295 break;
294 case CHAN_INPUT_WAIT_DRAIN: 296 case CHAN_INPUT_WAIT_DRAIN:
295 if (!(c->flags & CHAN_LOCAL)) 297 if (!(c->flags & CHAN_LOCAL))
296 chan_send_eof2(ssh, c); 298 chan_send_eof2(ssh, c);
299 chan_shutdown_extended_read(ssh, c);
297 chan_set_istate(c, CHAN_INPUT_CLOSED); 300 chan_set_istate(c, CHAN_INPUT_CLOSED);
298 break; 301 break;
299 } 302 }
@@ -422,3 +425,22 @@ chan_shutdown_read(struct ssh *ssh, Channel *c)
422 } 425 }
423 } 426 }
424} 427}
428
429static void
430chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
431{
432 if (c->type == SSH_CHANNEL_LARVAL || c->efd == -1)
433 return;
434 if (c->extended_usage != CHAN_EXTENDED_READ &&
435 c->extended_usage != CHAN_EXTENDED_IGNORE)
436 return;
437 debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
438 c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
439 channel_format_extended_usage(c));
440 if (channel_close_fd(ssh, &c->efd) < 0) {
441 logit("channel %d: %s: close() failed for "
442 "extended fd %d [i%d o%d]: %.100s",
443 c->self, __func__, c->efd, c->istate, c->ostate,
444 strerror(errno));
445 }
446}