diff --git a/SOURCES/openssh-6.7p1-coverity.patch b/SOURCES/openssh-6.7p1-coverity.patch index 15d489d..1d0bf27 100644 --- a/SOURCES/openssh-6.7p1-coverity.patch +++ b/SOURCES/openssh-6.7p1-coverity.patch @@ -1,21 +1,27 @@ -diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c ---- openssh-7.4p1/channels.c.coverity 2016-12-23 16:40:26.881788686 +0100 -+++ openssh-7.4p1/channels.c 2016-12-23 16:42:36.244818763 +0100 -@@ -288,11 +288,11 @@ channel_register_fds(Channel *c, int rfd +diff -up openssh-8.0p1/channels.c.coverity openssh-8.0p1/channels.c +--- openssh-8.0p1/channels.c.coverity 2021-04-26 11:49:58.725597484 +0200 ++++ openssh-8.0p1/channels.c 2021-04-26 12:03:17.756004774 +0200 +@@ -338,17 +338,17 @@ channel_register_fds(struct ssh *ssh, Ch + c->wfd_isatty = is_tty || isatty(c->wfd); + #endif - /* enable nonblocking mode */ - if (nonblock) { -- if (rfd != -1) -+ if (rfd >= 0) - set_nonblock(rfd); -- if (wfd != -1) -+ if (wfd >= 0) - set_nonblock(wfd); -- if (efd != -1) -+ if (efd >= 0) - set_nonblock(efd); +- if (rfd != -1) { ++ if (rfd >= 0) { + if ((fcntl(rfd, F_GETFL) & O_NONBLOCK) == 0) + c->nonblock |= NEED_RESTORE_STDIN_NONBLOCK; + channel_register_fd(ssh, rfd, nonblock); } - } +- if (wfd != -1 && wfd != rfd) { ++ if (wfd >= 0 && wfd != rfd) { + if ((fcntl(wfd, F_GETFL) & O_NONBLOCK) == 0) + c->nonblock |= NEED_RESTORE_STDOUT_NONBLOCK; + channel_register_fd(ssh, wfd, nonblock); + } +- if (efd != -1 && efd != rfd && efd != wfd) { ++ if (efd >= 0 && efd != rfd && efd != wfd) { + if ((fcntl(efd, F_GETFL) & O_NONBLOCK) == 0) + c->nonblock |= NEED_RESTORE_STDERR_NONBLOCK; + channel_register_fd(ssh, efd, nonblock); diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c --- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100 +++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100 diff --git a/SOURCES/openssh-8.0p1-restore-nonblock.patch b/SOURCES/openssh-8.0p1-restore-nonblock.patch new file mode 100644 index 0000000..cff647e --- /dev/null +++ b/SOURCES/openssh-8.0p1-restore-nonblock.patch @@ -0,0 +1,241 @@ +diff -up openssh-8.0p1/channels.c.restore-nonblock openssh-8.0p1/channels.c +--- openssh-8.0p1/channels.c.restore-nonblock 2021-04-26 11:31:44.037740711 +0200 ++++ openssh-8.0p1/channels.c 2021-04-26 11:43:48.429606396 +0200 +@@ -298,32 +298,38 @@ channel_lookup(struct ssh *ssh, int id) + } + + /* +- * Register filedescriptors for a channel, used when allocating a channel or +- * when the channel consumer/producer is ready, e.g. shell exec'd ++ * Register a filedescriptor. + */ + static void +-channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, +- int extusage, int nonblock, int is_tty) ++channel_register_fd(struct ssh *ssh, int fd, int nonblock) + { + struct ssh_channels *sc = ssh->chanctxt; + + /* Update the maximum file descriptor value. */ +- sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd); +- sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd); +- sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd); +- +- if (rfd != -1) +- fcntl(rfd, F_SETFD, FD_CLOEXEC); +- if (wfd != -1 && wfd != rfd) +- fcntl(wfd, F_SETFD, FD_CLOEXEC); +- if (efd != -1 && efd != rfd && efd != wfd) +- fcntl(efd, F_SETFD, FD_CLOEXEC); ++ sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, fd); ++ ++ if (fd != -1) ++ fcntl(fd, F_SETFD, FD_CLOEXEC); + ++ /* enable nonblocking mode */ ++ if (nonblock && fd != -1 && !isatty(fd)) ++ set_nonblock(fd); ++} ++ ++/* ++ * Register filedescriptors for a channel, used when allocating a channel or ++ * when the channel consumer/producer is ready, e.g. shell exec'd ++ */ ++static void ++channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, ++ int extusage, int nonblock, int is_tty) ++{ + c->rfd = rfd; + c->wfd = wfd; + c->sock = (rfd == wfd) ? rfd : -1; + c->efd = efd; + c->extended_usage = extusage; ++ c->nonblock = 0; + + if ((c->isatty = is_tty) != 0) + debug2("channel %d: rfd %d isatty", c->self, c->rfd); +@@ -332,14 +338,20 @@ channel_register_fds(struct ssh *ssh, Ch + c->wfd_isatty = is_tty || isatty(c->wfd); + #endif + +- /* enable nonblocking mode */ +- if (nonblock) { +- if (rfd != -1) +- set_nonblock(rfd); +- if (wfd != -1) +- set_nonblock(wfd); +- if (efd != -1) +- set_nonblock(efd); ++ if (rfd != -1) { ++ if ((fcntl(rfd, F_GETFL) & O_NONBLOCK) == 0) ++ c->nonblock |= NEED_RESTORE_STDIN_NONBLOCK; ++ channel_register_fd(ssh, rfd, nonblock); ++ } ++ if (wfd != -1 && wfd != rfd) { ++ if ((fcntl(wfd, F_GETFL) & O_NONBLOCK) == 0) ++ c->nonblock |= NEED_RESTORE_STDOUT_NONBLOCK; ++ channel_register_fd(ssh, wfd, nonblock); ++ } ++ if (efd != -1 && efd != rfd && efd != wfd) { ++ if ((fcntl(efd, F_GETFL) & O_NONBLOCK) == 0) ++ c->nonblock |= NEED_RESTORE_STDERR_NONBLOCK; ++ channel_register_fd(ssh, efd, nonblock); + } + } + +@@ -422,11 +434,15 @@ channel_find_maxfd(struct ssh_channels * + } + + int +-channel_close_fd(struct ssh *ssh, int *fdp) ++channel_close_fd(struct ssh *ssh, int *fdp, int nonblock) + { + struct ssh_channels *sc = ssh->chanctxt; + int ret = 0, fd = *fdp; + ++ /* As the fd is duped, restoring the block mode ++ * affects the original fd */ ++ if (nonblock && fd != -1 && !isatty(fd)) ++ unset_nonblock(fd); + if (fd != -1) { + ret = close(fd); + *fdp = -1; +@@ -442,13 +458,13 @@ channel_close_fds(struct ssh *ssh, Chann + { + int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; + +- channel_close_fd(ssh, &c->sock); ++ channel_close_fd(ssh, &c->sock, 0); + if (rfd != sock) +- channel_close_fd(ssh, &c->rfd); ++ channel_close_fd(ssh, &c->rfd, c->nonblock & NEED_RESTORE_STDIN_NONBLOCK); + if (wfd != sock && wfd != rfd) +- channel_close_fd(ssh, &c->wfd); ++ channel_close_fd(ssh, &c->wfd, c->nonblock & NEED_RESTORE_STDOUT_NONBLOCK); + if (efd != sock && efd != rfd && efd != wfd) +- channel_close_fd(ssh, &c->efd); ++ channel_close_fd(ssh, &c->efd, c->nonblock & NEED_RESTORE_STDERR_NONBLOCK); + } + + static void +@@ -681,7 +697,7 @@ channel_stop_listening(struct ssh *ssh) + case SSH_CHANNEL_X11_LISTENER: + case SSH_CHANNEL_UNIX_LISTENER: + case SSH_CHANNEL_RUNIX_LISTENER: +- channel_close_fd(ssh, &c->sock); ++ channel_close_fd(ssh, &c->sock, 0); + channel_free(ssh, c); + break; + } +@@ -1650,7 +1666,7 @@ channel_post_x11_listener(struct ssh *ss + if (c->single_connection) { + oerrno = errno; + debug2("single_connection: closing X11 listener."); +- channel_close_fd(ssh, &c->sock); ++ channel_close_fd(ssh, &c->sock, 0); + chan_mark_dead(ssh, c); + errno = oerrno; + } +@@ -2087,7 +2103,7 @@ channel_handle_efd_write(struct ssh *ssh + return 1; + if (len <= 0) { + debug2("channel %d: closing write-efd %d", c->self, c->efd); +- channel_close_fd(ssh, &c->efd); ++ channel_close_fd(ssh, &c->efd, c->nonblock & NEED_RESTORE_STDERR_NONBLOCK); + } else { + if ((r = sshbuf_consume(c->extended, len)) != 0) { + fatal("%s: channel %d: consume: %s", +@@ -2119,7 +2135,7 @@ channel_handle_efd_read(struct ssh *ssh, + if (len <= 0) { + debug2("channel %d: closing read-efd %d", + c->self, c->efd); +- channel_close_fd(ssh, &c->efd); ++ channel_close_fd(ssh, &c->efd, c->nonblock & NEED_RESTORE_STDERR_NONBLOCK); + } else { + if (c->extended_usage == CHAN_EXTENDED_IGNORE) { + debug3("channel %d: discard efd", +diff -up openssh-8.0p1/channels.h.restore-nonblock openssh-8.0p1/channels.h +--- openssh-8.0p1/channels.h.restore-nonblock 2021-04-26 11:31:44.038740719 +0200 ++++ openssh-8.0p1/channels.h 2021-04-26 11:38:18.151932008 +0200 +@@ -180,8 +180,15 @@ struct Channel { + void *mux_ctx; + int mux_pause; + int mux_downstream_id; ++ ++ /* whether non-blocking is set to descriptors */ ++ int nonblock; + }; + ++#define NEED_RESTORE_STDIN_NONBLOCK 1 ++#define NEED_RESTORE_STDOUT_NONBLOCK 2 ++#define NEED_RESTORE_STDERR_NONBLOCK 4 ++ + #define CHAN_EXTENDED_IGNORE 0 + #define CHAN_EXTENDED_READ 1 + #define CHAN_EXTENDED_WRITE 2 +@@ -258,7 +265,7 @@ void channel_register_filter(struct ssh + void channel_register_status_confirm(struct ssh *, int, + channel_confirm_cb *, channel_confirm_abandon_cb *, void *); + void channel_cancel_cleanup(struct ssh *, int); +-int channel_close_fd(struct ssh *, int *); ++int channel_close_fd(struct ssh *, int *, int); + void channel_send_window_changes(struct ssh *); + + /* mux proxy support */ +diff -up openssh-8.0p1/nchan.c.restore-nonblock openssh-8.0p1/nchan.c +--- openssh-8.0p1/nchan.c.restore-nonblock 2021-04-26 11:31:44.047740792 +0200 ++++ openssh-8.0p1/nchan.c 2021-04-26 11:42:33.636000753 +0200 +@@ -387,7 +387,7 @@ chan_shutdown_write(struct ssh *ssh, Cha + strerror(errno)); + } + } else { +- if (channel_close_fd(ssh, &c->wfd) < 0) { ++ if (channel_close_fd(ssh, &c->wfd, c->nonblock & NEED_RESTORE_STDOUT_NONBLOCK) < 0) { + logit("channel %d: %s: close() failed for " + "fd %d [i%d o%d]: %.100s", + c->self, __func__, c->wfd, c->istate, c->ostate, +@@ -417,7 +417,7 @@ chan_shutdown_read(struct ssh *ssh, Chan + strerror(errno)); + } + } else { +- if (channel_close_fd(ssh, &c->rfd) < 0) { ++ if (channel_close_fd(ssh, &c->rfd, c->nonblock & NEED_RESTORE_STDIN_NONBLOCK) < 0) { + logit("channel %d: %s: close() failed for " + "fd %d [i%d o%d]: %.100s", + c->self, __func__, c->rfd, c->istate, c->ostate, +@@ -437,7 +437,7 @@ chan_shutdown_extended_read(struct ssh * + debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd, + channel_format_extended_usage(c)); +- if (channel_close_fd(ssh, &c->efd) < 0) { ++ if (channel_close_fd(ssh, &c->efd, c->nonblock & NEED_RESTORE_STDERR_NONBLOCK) < 0) { + logit("channel %d: %s: close() failed for " + "extended fd %d [i%d o%d]: %.100s", + c->self, __func__, c->efd, c->istate, c->ostate, +diff -up openssh-8.0p1/ssh.c.restore-nonblock openssh-8.0p1/ssh.c +--- openssh-8.0p1/ssh.c.restore-nonblock 2021-04-26 11:31:44.047740792 +0200 ++++ openssh-8.0p1/ssh.c 2021-04-26 11:39:58.081741180 +0200 +@@ -1862,14 +1862,6 @@ ssh_session2_open(struct ssh *ssh) + if (in < 0 || out < 0 || err < 0) + fatal("dup() in/out/err failed"); + +- /* enable nonblocking unless tty */ +- if (!isatty(in)) +- set_nonblock(in); +- if (!isatty(out)) +- set_nonblock(out); +- if (!isatty(err)) +- set_nonblock(err); +- + window = CHAN_SES_WINDOW_DEFAULT; + packetmax = CHAN_SES_PACKET_DEFAULT; + if (tty_flag) { +@@ -1879,7 +1871,7 @@ ssh_session2_open(struct ssh *ssh) + c = channel_new(ssh, + "session", SSH_CHANNEL_OPENING, in, out, err, + window, packetmax, CHAN_EXTENDED_WRITE, +- "client-session", /*nonblock*/0); ++ "client-session", /*nonblock*/1); + + debug3("%s: channel_new: %d", __func__, c->self); + diff --git a/SPECS/openssh.spec b/SPECS/openssh.spec index bd8260f..46d1f12 100644 --- a/SPECS/openssh.spec +++ b/SPECS/openssh.spec @@ -66,7 +66,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 8.0p1 -%global openssh_rel 7 +%global openssh_rel 8 %global pam_ssh_agent_ver 0.10.3 %global pam_ssh_agent_rel 7 @@ -239,6 +239,8 @@ Patch973: openssh-8.0p1-sftp-timespeccmp.patch Patch974: openssh-8.0p1-keygen-strip-doseol.patch # sshd provides PAM an incorrect error code (#1879503) Patch975: openssh-8.0p1-preserve-pam-errors.patch +# ssh incorrectly restores the blocking mode on standard output (#1942901) +Patch976: openssh-8.0p1-restore-nonblock.patch License: BSD Group: Applications/Internet @@ -461,6 +463,7 @@ popd %patch973 -p1 -b .sftp-timespeccmp %patch974 -p1 -b .keygen-strip-doseol %patch975 -p1 -b .preserve-pam-errors +%patch976 -p1 -b .restore-nonblock %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race @@ -752,6 +755,9 @@ getent passwd sshd >/dev/null || \ %endif %changelog +* Mon Apr 26 2021 Dmitry Belyavskiy - 8.0p1-8 +- ssh doesn't restore the blocking mode on standard output (#1942901) + * Fri Apr 09 2021 Dmitry Belyavskiy - 8.0p1-7 + 0.10.3-7 - SFTP sort upon the modification time (#1909988) - ssh-keygen printing fingerprint issue with Windows keys (#1901518)