Index: crypto/external/bsd/openssh/dist/channels.c =================================================================== RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/channels.c,v retrieving revision 1.36 diff -p -u -r1.36 channels.c --- crypto/external/bsd/openssh/dist/channels.c 15 Apr 2022 14:00:06 -0000 1.36 +++ crypto/external/bsd/openssh/dist/channels.c 1 Aug 2022 20:24:16 -0000 @@ -1117,9 +1117,9 @@ channel_tcpwinsz(struct ssh *ssh) return(128*1024); ret = getsockopt(ssh_packet_get_connection_in(ssh), SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz); - /* return no more than 64MB */ - if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN) - tcpwinsz = BUFFER_MAX_LEN_HPN; + /* return no more than SSHBUF_SIZE_MAX (currently 256MB) */ + if ((ret == 0) && tcpwinsz > SSHBUF_SIZE_MAX) + tcpwinsz = SSHBUF_SIZE_MAX; debug2("tcpwinsz: %d for connection: %d", tcpwinsz, ssh_packet_get_connection_in(ssh)); return(tcpwinsz); @@ -1128,10 +1128,6 @@ channel_tcpwinsz(struct ssh *ssh) static void channel_pre_open(struct ssh *ssh, Channel *c) { - /* check buffer limits */ - if ((!c->tcpwinsz) || (c->dynamic_window > 0)) - c->tcpwinsz = channel_tcpwinsz(ssh); - c->io_want = 0; if (c->istate == CHAN_INPUT_OPEN && c->remote_window > 0 && @@ -2170,17 +2166,17 @@ channel_check_window(struct ssh *ssh, Ch c->local_window < c->local_window_max/2) && c->local_consumed > 0) { u_int addition = 0; - - if (!c->have_remote_id) - fatal_f("channel %d: no remote id", c->self); - + u_int32_t tcpwinsz = channel_tcpwinsz(ssh); /* adjust max window size if we are in a dynamic environment */ - if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) { + if (c->dynamic_window && (tcpwinsz > c->local_window_max)) { /* grow the window somewhat aggressively to maintain * pressure */ - addition = 1.5*(c->tcpwinsz - c->local_window_max); + addition = 1.5*(tcpwinsz - c->local_window_max); c->local_window_max += addition; + debug("Channel: Window growth to %d by %d bytes", c->local_window_max, addition); } + if (!c->have_remote_id) + fatal_f("channel %d: no remote id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || @@ -2189,7 +2185,8 @@ channel_check_window(struct ssh *ssh, Ch fatal_fr(r, "channel %i", c->self); } debug2("channel %d: window %d sent adjust %d", c->self, - c->local_window, c->local_consumed); + c->local_window, + c->local_consumed + addition); c->local_window += c->local_consumed + addition; c->local_consumed = 0; } Index: crypto/external/bsd/openssh/dist/readconf.c =================================================================== RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/readconf.c,v retrieving revision 1.38 diff -p -u -r1.38 readconf.c --- crypto/external/bsd/openssh/dist/readconf.c 23 Feb 2022 19:07:20 -0000 1.38 +++ crypto/external/bsd/openssh/dist/readconf.c 1 Aug 2022 20:24:16 -0000 @@ -42,6 +42,7 @@ __RCSID("$NetBSD: readconf.c,v 1.38 2022 #include "xmalloc.h" #include "ssh.h" +#include "sshbuf.h" #include "ssherr.h" #include "compat.h" #include "cipher.h" @@ -2711,13 +2712,14 @@ fill_default_options(Options * options) { /* if a user tries to set the size to 0 set it to 1KB */ if (options->hpn_buffer_size == 0) - options->hpn_buffer_size = 1024; + options->hpn_buffer_size = 1; /*limit the buffer to 64MB*/ - if (options->hpn_buffer_size > 65536) + if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024)) { - options->hpn_buffer_size = 65536*1024; - debug("User requested buffer larger than 64MB. Request reverted to 64MB"); - } + options->hpn_buffer_size = SSHBUF_SIZE_MAX; + debug("User requested buffer larger than 256MB. Request reverted to 256MB"); + } else + options->hpn_buffer_size *= 1024; debug("hpn_buffer_size set to %d", options->hpn_buffer_size); } if (options->tcp_rcv_buf == 0) Index: crypto/external/bsd/openssh/dist/ssh.c =================================================================== RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/ssh.c,v retrieving revision 1.40 diff -p -u -r1.40 ssh.c --- crypto/external/bsd/openssh/dist/ssh.c 15 Apr 2022 14:00:06 -0000 1.40 +++ crypto/external/bsd/openssh/dist/ssh.c 1 Aug 2022 20:24:16 -0000 @@ -2046,15 +2046,85 @@ ssh_session2_setup(struct ssh *ssh, int NULL, fileno(stdin), command, environ); } +static void +hpn_options_init(struct ssh *ssh) +{ + /* + * We need to check to see if what they want to do about buffer + * sizes here. In a hpn to nonhpn connection we want to limit + * the window size to something reasonable in case the far side + * has the large window bug. In hpn to hpn connection we want to + * use the max window size but allow the user to override it + * lastly if they disabled hpn then use the ssh std window size. + * + * So why don't we just do a getsockopt() here and set the + * ssh window to that? In the case of a autotuning receive + * window the window would get stuck at the initial buffer + * size generally less than 96k. Therefore we need to set the + * maximum ssh window size to the maximum hpn buffer size + * unless the user has specifically set the tcprcvbufpoll + * to no. In which case we *can* just set the window to the + * minimum of the hpn buffer size and tcp receive buffer size. + */ + + if (tty_flag) + options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; + else + options.hpn_buffer_size = 2 * 1024 * 1024; + + if (ssh->compat & SSH_BUG_LARGEWINDOW) { + debug("HPN to Non-HPN connection"); + } else { + debug("HPN to HPN connection"); + int sock, socksize; + socklen_t socksizelen; + if (options.tcp_rcv_buf_poll <= 0) { + sock = socket(AF_INET, SOCK_STREAM, 0); + socksizelen = sizeof(socksize); + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, + &socksize, &socksizelen); + close(sock); + debug("socksize %d", socksize); + options.hpn_buffer_size = socksize; + debug("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); + } else { + if (options.tcp_rcv_buf > 0) { + /* + * Create a socket but don't connect it: + * we use that the get the rcv socket size + */ + sock = socket(AF_INET, SOCK_STREAM, 0); + /* + * If they are using the tcp_rcv_buf option, + * attempt to set the buffer size to that. + */ + if (options.tcp_rcv_buf) { + socksizelen = sizeof(options.tcp_rcv_buf); + setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + &options.tcp_rcv_buf, socksizelen); + } + socksizelen = sizeof(socksize); + getsockopt(sock, SOL_SOCKET, SO_RCVBUF, + &socksize, &socksizelen); + close(sock); + debug("socksize %d", socksize); + options.hpn_buffer_size = socksize; + debug("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); + } + } + } + + debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); + + channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); +} + /* open new channel for a session */ static int ssh_session2_open(struct ssh *ssh) { Channel *c; int window, packetmax, in, out, err; - int sock; - int socksize; - socklen_t socksizelen = sizeof(int); if (options.stdin_null) { in = open(_PATH_DEVNULL, O_RDONLY); @@ -2075,60 +2145,7 @@ ssh_session2_open(struct ssh *ssh) if (!isatty(err)) set_nonblock(err); - /* we need to check to see if what they want to do about buffer */ - /* sizes here. In a hpn to nonhpn connection we want to limit */ - /* the window size to something reasonable in case the far side */ - /* has the large window bug. In hpn to hpn connection we want to */ - /* use the max window size but allow the user to override it */ - /* lastly if they disabled hpn then use the ssh std window size */ - - /* so why don't we just do a getsockopt() here and set the */ - /* ssh window to that? In the case of a autotuning receive */ - /* window the window would get stuck at the initial buffer */ - /* size generally less than 96k. Therefore we need to set the */ - /* maximum ssh window size to the maximum hpn buffer size */ - /* unless the user has specifically set the tcprcvbufpoll */ - /* to no. In which case we *can* just set the window to the */ - /* minimum of the hpn buffer size and tcp receive buffer size */ - - if (tty_flag) - options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT; - else - options.hpn_buffer_size = 2*1024*1024; - - if (options.tcp_rcv_buf_poll <= 0) { - sock = socket(AF_INET, SOCK_STREAM, 0); - getsockopt(sock, SOL_SOCKET, SO_RCVBUF, - &socksize, &socksizelen); - close(sock); - debug("socksize %d", socksize); - options.hpn_buffer_size = socksize; - debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size); - } else { - if (options.tcp_rcv_buf > 0) { - /*create a socket but don't connect it */ - /* we use that the get the rcv socket size */ - sock = socket(AF_INET, SOCK_STREAM, 0); - /* if they are using the tcp_rcv_buf option */ - /* attempt to set the buffer size to that */ - if (options.tcp_rcv_buf) - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, - sizeof(options.tcp_rcv_buf)); - getsockopt(sock, SOL_SOCKET, SO_RCVBUF, - &socksize, &socksizelen); - close(sock); - debug("socksize %d", socksize); - options.hpn_buffer_size = socksize; - debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size); - } - } - - debug("Final hpn_buffer_size = %d", options.hpn_buffer_size); - window = options.hpn_buffer_size; - - channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); - packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window = 4*CHAN_SES_PACKET_DEFAULT; @@ -2160,6 +2177,13 @@ ssh_session2(struct ssh *ssh, const stru int r, id = -1; char *cp, *tun_fwd_ifname = NULL; + /* + * We need to initialize this early because the forwarding logic below + * might open channels that use the hpn buffer sizes. We can't send a + * window of -1 (the default) to the server as it breaks things. + */ + hpn_options_init(ssh); + /* XXX should be pre-session */ if (!options.control_persist) ssh_init_stdio_forwarding(ssh); Index: crypto/external/bsd/openssh/dist/sshbuf.h =================================================================== RCS file: /cvsroot/src/crypto/external/bsd/openssh/dist/sshbuf.h,v retrieving revision 1.16 diff -p -u -r1.16 sshbuf.h --- crypto/external/bsd/openssh/dist/sshbuf.h 23 Feb 2022 19:07:20 -0000 1.16 +++ crypto/external/bsd/openssh/dist/sshbuf.h 1 Aug 2022 20:24:16 -0000 @@ -34,10 +34,7 @@ #define EC_POINT void #endif /* WITH_OPENSSL */ -/* move the following to a more appropriate place and name */ -#define BUFFER_MAX_LEN_HPN 0x4000000 /* 64MB */ - -#define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */ +#define SSHBUF_SIZE_MAX 0x10000000 /* Hard maximum size 256MB */ #define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */ #define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */ #define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */