when restoring non-blocking mode to stdio fds, restore exactly
authordjm <djm@openbsd.org>
Wed, 18 Jan 2023 02:00:10 +0000 (02:00 +0000)
committerdjm <djm@openbsd.org>
Wed, 18 Jan 2023 02:00:10 +0000 (02:00 +0000)
the flags that ssh started with and don't just clobber them with
zero, as this could also remove the append flag from the set;

bz3523; ok dtucker@

usr.bin/ssh/channels.c
usr.bin/ssh/channels.h

index c7b4c2a..3153dab 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.426 2023/01/06 02:47:18 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.427 2023/01/18 02:00:10 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -405,16 +405,19 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
                 */
                if (rfd != -1 && !isatty(rfd) &&
                    (val = fcntl(rfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) {
+                       c->restore_flags[0] = val;
                        c->restore_block |= CHANNEL_RESTORE_RFD;
                        set_nonblock(rfd);
                }
                if (wfd != -1 && !isatty(wfd) &&
                    (val = fcntl(wfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) {
+                       c->restore_flags[1] = val;
                        c->restore_block |= CHANNEL_RESTORE_WFD;
                        set_nonblock(wfd);
                }
                if (efd != -1 && !isatty(efd) &&
                    (val = fcntl(efd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) {
+                       c->restore_flags[2] = val;
                        c->restore_block |= CHANNEL_RESTORE_EFD;
                        set_nonblock(efd);
                }
@@ -498,10 +501,16 @@ channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
        if (fd == -1)
                return 0;
 
-       if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) ||
-          (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) ||
-          (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0))
-               (void)fcntl(*fdp, F_SETFL, 0);  /* restore blocking */
+       /* restore blocking */
+       if (*fdp == c->rfd &&
+           (c->restore_block & CHANNEL_RESTORE_RFD) != 0)
+               (void)fcntl(*fdp, F_SETFL, c->restore_flags[0]);
+       else if (*fdp == c->wfd &&
+           (c->restore_block & CHANNEL_RESTORE_WFD) != 0)
+               (void)fcntl(*fdp, F_SETFL, c->restore_flags[1]);
+       else if (*fdp == c->efd &&
+           (c->restore_block & CHANNEL_RESTORE_EFD) != 0)
+               (void)fcntl(*fdp, F_SETFL, c->restore_flags[2]);
 
        if (*fdp == c->rfd) {
                c->io_want &= ~SSH_CHAN_IO_RFD;
index 8d4699a..853ac98 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.147 2023/01/06 02:47:18 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.148 2023/01/18 02:00:10 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -150,6 +150,7 @@ struct Channel {
                                 * this way post-IO handlers are not
                                 * accidentally called if a FD gets reused */
        int     restore_block;  /* fd mask to restore blocking status */
+       int     restore_flags[3];/* flags to restore */
        struct sshbuf *input;   /* data read from socket, to be sent over
                                 * encrypted connection */
        struct sshbuf *output;  /* data received over encrypted connection for