diff options
author | Ed Maste <emaste@FreeBSD.org> | 2022-04-08 17:19:17 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2022-04-08 17:19:17 +0000 |
commit | 7f9f5c27f6f623a2081f2b436692418fd962b903 (patch) | |
tree | 569d31cd1a0c415a8db48bba8251b77535819a76 /channels.c | |
parent | 9b7e085bc027cd9fe4c54e71b49e276559d82983 (diff) | |
download | src-7f9f5c27f6f623a2081f2b436692418fd962b903.tar.gz src-7f9f5c27f6f623a2081f2b436692418fd962b903.zip |
Vendor import of OpenSSH 9.0p1vendor/openssh/9.0p1
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 222 |
1 files changed, 118 insertions, 104 deletions
diff --git a/channels.c b/channels.c index 73e93c032765..ee3c787922fb 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.413 2022/02/17 10:58:27 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.415 2022/03/30 21:10:25 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -432,21 +432,25 @@ channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) c->io_want &= ~SSH_CHAN_IO_RFD; c->io_ready &= ~SSH_CHAN_IO_RFD; c->rfd = -1; + c->pfds[0] = -1; } if (*fdp == c->wfd) { c->io_want &= ~SSH_CHAN_IO_WFD; c->io_ready &= ~SSH_CHAN_IO_WFD; c->wfd = -1; + c->pfds[1] = -1; } if (*fdp == c->efd) { c->io_want &= ~SSH_CHAN_IO_EFD; c->io_ready &= ~SSH_CHAN_IO_EFD; c->efd = -1; + c->pfds[2] = -1; } if (*fdp == c->sock) { c->io_want &= ~SSH_CHAN_IO_SOCK; c->io_ready &= ~SSH_CHAN_IO_SOCK; c->sock = -1; + c->pfds[3] = -1; } ret = close(fd); @@ -2475,10 +2479,13 @@ dump_channel_poll(const char *func, const char *what, Channel *c, u_int pollfd_offset, struct pollfd *pfd) { #ifdef DEBUG_CHANNEL_POLL - debug3_f("channel %d: rfd r%d w%d e%d s%d " - "pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x", - c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset, pfd->fd, - c->io_want, pfd->events, c->io_ready, pfd->revents); + debug3("%s: channel %d: %s r%d w%d e%d s%d c->pfds [ %d %d %d %d ] " + "io_want 0x%02x io_ready 0x%02x pfd[%u].fd=%d " + "pfd.ev 0x%02x pfd.rev 0x%02x", func, c->self, what, + c->rfd, c->wfd, c->efd, c->sock, + c->pfds[0], c->pfds[1], c->pfds[2], c->pfds[3], + c->io_want, c->io_ready, + pollfd_offset, pfd->fd, pfd->events, pfd->revents); #endif } @@ -2487,7 +2494,7 @@ static void channel_prepare_pollfd(Channel *c, u_int *next_pollfd, struct pollfd *pfd, u_int npfd) { - u_int p = *next_pollfd; + u_int ev, p = *next_pollfd; if (c == NULL) return; @@ -2496,7 +2503,7 @@ channel_prepare_pollfd(Channel *c, u_int *next_pollfd, fatal_f("channel %d: bad pfd offset %u (max %u)", c->self, p, npfd); } - c->pollfd_offset = -1; + c->pfds[0] = c->pfds[1] = c->pfds[2] = c->pfds[3] = -1; /* * prepare c->rfd * @@ -2505,69 +2512,82 @@ channel_prepare_pollfd(Channel *c, u_int *next_pollfd, * IO too. */ if (c->rfd != -1) { - if (c->pollfd_offset == -1) - c->pollfd_offset = p; - pfd[p].fd = c->rfd; - pfd[p].events = 0; + ev = 0; if ((c->io_want & SSH_CHAN_IO_RFD) != 0) - pfd[p].events |= POLLIN; + ev |= POLLIN; /* rfd == wfd */ - if (c->wfd == c->rfd && - (c->io_want & SSH_CHAN_IO_WFD) != 0) - pfd[p].events |= POLLOUT; + if (c->wfd == c->rfd) { + if ((c->io_want & SSH_CHAN_IO_WFD) != 0) + ev |= POLLOUT; + } /* rfd == efd */ - if (c->efd == c->rfd && - (c->io_want & SSH_CHAN_IO_EFD_R) != 0) - pfd[p].events |= POLLIN; - if (c->efd == c->rfd && - (c->io_want & SSH_CHAN_IO_EFD_W) != 0) - pfd[p].events |= POLLOUT; + if (c->efd == c->rfd) { + if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) + ev |= POLLIN; + if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) + ev |= POLLOUT; + } /* rfd == sock */ - if (c->sock == c->rfd && - (c->io_want & SSH_CHAN_IO_SOCK_R) != 0) - pfd[p].events |= POLLIN; - if (c->sock == c->rfd && - (c->io_want & SSH_CHAN_IO_SOCK_W) != 0) - pfd[p].events |= POLLOUT; - dump_channel_poll(__func__, "rfd", c, p, &pfd[p]); - p++; - } - /* prepare c->wfd (if not already handled above) */ + if (c->sock == c->rfd) { + if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) + ev |= POLLIN; + if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) + ev |= POLLOUT; + } + /* Pack a pfd entry if any event armed for this fd */ + if (ev != 0) { + c->pfds[0] = p; + pfd[p].fd = c->rfd; + pfd[p].events = ev; + dump_channel_poll(__func__, "rfd", c, p, &pfd[p]); + p++; + } + } + /* prepare c->wfd if wanting IO and not already handled above */ if (c->wfd != -1 && c->rfd != c->wfd) { - if (c->pollfd_offset == -1) - c->pollfd_offset = p; - pfd[p].fd = c->wfd; - pfd[p].events = 0; - if ((c->io_want & SSH_CHAN_IO_WFD) != 0) - pfd[p].events = POLLOUT; - dump_channel_poll(__func__, "wfd", c, p, &pfd[p]); - p++; - } - /* prepare c->efd (if not already handled above) */ + ev = 0; + if ((c->io_want & SSH_CHAN_IO_WFD)) + ev |= POLLOUT; + /* Pack a pfd entry if any event armed for this fd */ + if (ev != 0) { + c->pfds[1] = p; + pfd[p].fd = c->wfd; + pfd[p].events = ev; + dump_channel_poll(__func__, "wfd", c, p, &pfd[p]); + p++; + } + } + /* prepare c->efd if wanting IO and not already handled above */ if (c->efd != -1 && c->rfd != c->efd) { - if (c->pollfd_offset == -1) - c->pollfd_offset = p; - pfd[p].fd = c->efd; - pfd[p].events = 0; + ev = 0; if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) - pfd[p].events |= POLLIN; + ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) - pfd[p].events |= POLLOUT; - dump_channel_poll(__func__, "efd", c, p, &pfd[p]); - p++; + ev |= POLLOUT; + /* Pack a pfd entry if any event armed for this fd */ + if (ev != 0) { + c->pfds[2] = p; + pfd[p].fd = c->efd; + pfd[p].events = ev; + dump_channel_poll(__func__, "efd", c, p, &pfd[p]); + p++; + } } - /* prepare c->sock (if not already handled above) */ + /* prepare c->sock if wanting IO and not already handled above */ if (c->sock != -1 && c->rfd != c->sock) { - if (c->pollfd_offset == -1) - c->pollfd_offset = p; - pfd[p].fd = c->sock; - pfd[p].events = 0; + ev = 0; if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) - pfd[p].events |= POLLIN; + ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) - pfd[p].events |= POLLOUT; - dump_channel_poll(__func__, "sock", c, p, &pfd[p]); - p++; + ev |= POLLOUT; + /* Pack a pfd entry if any event armed for this fd */ + if (ev != 0) { + c->pfds[3] = p; + pfd[p].fd = c->sock; + pfd[p].events = 0; + dump_channel_poll(__func__, "sock", c, p, &pfd[p]); + p++; + } } *next_pollfd = p; } @@ -2614,13 +2634,15 @@ channel_prepare_poll(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, } static void -fd_ready(Channel *c, u_int p, struct pollfd *pfds, int fd, +fd_ready(Channel *c, int p, struct pollfd *pfds, u_int npfd, int fd, const char *what, u_int revents_mask, u_int ready) { struct pollfd *pfd = &pfds[p]; if (fd == -1) return; + if (p == -1 || (u_int)p >= npfd) + fatal_f("channel %d: bad pfd %d (max %u)", c->self, p, npfd); dump_channel_poll(__func__, what, c, p, pfd); if (pfd->fd != fd) { fatal("channel %d: inconsistent %s fd=%d pollfd[%u].fd %d " @@ -2643,11 +2665,12 @@ void channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) { struct ssh_channels *sc = ssh->chanctxt; - u_int i, p; + u_int i; + int p; Channel *c; #ifdef DEBUG_CHANNEL_POLL - for (p = 0; p < npfd; p++) { + for (p = 0; p < (int)npfd; p++) { if (pfd[p].revents == 0) continue; debug_f("pfd[%u].fd %d rev 0x%04x", @@ -2658,13 +2681,8 @@ channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) /* Convert pollfd into c->io_ready */ for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; - if (c == NULL || c->pollfd_offset < 0) + if (c == NULL) continue; - if ((u_int)c->pollfd_offset >= npfd) { - /* shouldn't happen */ - fatal_f("channel %d: (before) bad pfd %u (max %u)", - c->self, c->pollfd_offset, npfd); - } /* if rfd is shared with efd/sock then wfd should be too */ if (c->rfd != -1 && c->wfd != -1 && c->rfd != c->wfd && (c->rfd == c->efd || c->rfd == c->sock)) { @@ -2673,56 +2691,52 @@ channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) c->self, c->rfd, c->wfd, c->efd, c->sock); } c->io_ready = 0; - p = c->pollfd_offset; /* rfd, potentially shared with wfd, efd and sock */ - if (c->rfd != -1) { - fd_ready(c, p, pfd, c->rfd, "rfd", POLLIN, - SSH_CHAN_IO_RFD); + if (c->rfd != -1 && (p = c->pfds[0]) != -1) { + fd_ready(c, p, pfd, npfd, c->rfd, + "rfd", POLLIN, SSH_CHAN_IO_RFD); if (c->rfd == c->wfd) { - fd_ready(c, p, pfd, c->wfd, "wfd/r", POLLOUT, - SSH_CHAN_IO_WFD); + fd_ready(c, p, pfd, npfd, c->wfd, + "wfd/r", POLLOUT, SSH_CHAN_IO_WFD); } if (c->rfd == c->efd) { - fd_ready(c, p, pfd, c->efd, "efdr/r", POLLIN, - SSH_CHAN_IO_EFD_R); - fd_ready(c, p, pfd, c->efd, "efdw/r", POLLOUT, - SSH_CHAN_IO_EFD_W); + fd_ready(c, p, pfd, npfd, c->efd, + "efdr/r", POLLIN, SSH_CHAN_IO_EFD_R); + fd_ready(c, p, pfd, npfd, c->efd, + "efdw/r", POLLOUT, SSH_CHAN_IO_EFD_W); } if (c->rfd == c->sock) { - fd_ready(c, p, pfd, c->sock, "sockr/r", POLLIN, - SSH_CHAN_IO_SOCK_R); - fd_ready(c, p, pfd, c->sock, "sockw/r", POLLOUT, - SSH_CHAN_IO_SOCK_W); + fd_ready(c, p, pfd, npfd, c->sock, + "sockr/r", POLLIN, SSH_CHAN_IO_SOCK_R); + fd_ready(c, p, pfd, npfd, c->sock, + "sockw/r", POLLOUT, SSH_CHAN_IO_SOCK_W); } - p++; + dump_channel_poll(__func__, "rfd", c, p, pfd); } /* wfd */ - if (c->wfd != -1 && c->wfd != c->rfd) { - fd_ready(c, p, pfd, c->wfd, "wfd", POLLOUT, - SSH_CHAN_IO_WFD); - p++; + if (c->wfd != -1 && c->wfd != c->rfd && + (p = c->pfds[1]) != -1) { + fd_ready(c, p, pfd, npfd, c->wfd, + "wfd", POLLOUT, SSH_CHAN_IO_WFD); + dump_channel_poll(__func__, "wfd", c, p, pfd); } /* efd */ - if (c->efd != -1 && c->efd != c->rfd) { - fd_ready(c, p, pfd, c->efd, "efdr", POLLIN, - SSH_CHAN_IO_EFD_R); - fd_ready(c, p, pfd, c->efd, "efdw", POLLOUT, - SSH_CHAN_IO_EFD_W); - p++; + if (c->efd != -1 && c->efd != c->rfd && + (p = c->pfds[2]) != -1) { + fd_ready(c, p, pfd, npfd, c->efd, + "efdr", POLLIN, SSH_CHAN_IO_EFD_R); + fd_ready(c, p, pfd, npfd, c->efd, + "efdw", POLLOUT, SSH_CHAN_IO_EFD_W); + dump_channel_poll(__func__, "efd", c, p, pfd); } /* sock */ - if (c->sock != -1 && c->sock != c->rfd) { - fd_ready(c, p, pfd, c->sock, "sockr", POLLIN, - SSH_CHAN_IO_SOCK_R); - fd_ready(c, p, pfd, c->sock, "sockw", POLLOUT, - SSH_CHAN_IO_SOCK_W); - p++; - } - - if (p > npfd) { - /* shouldn't happen */ - fatal_f("channel %d: (after) bad pfd %u (max %u)", - c->self, c->pollfd_offset, npfd); + if (c->sock != -1 && c->sock != c->rfd && + (p = c->pfds[3]) != -1) { + fd_ready(c, p, pfd, npfd, c->sock, + "sockr", POLLIN, SSH_CHAN_IO_SOCK_R); + fd_ready(c, p, pfd, npfd, c->sock, + "sockw", POLLOUT, SSH_CHAN_IO_SOCK_W); + dump_channel_poll(__func__, "sock", c, p, pfd); } } channel_handler(ssh, CHAN_POST, NULL); |