[openssh-commits] [openssh] 06/07: upstream: Use sshbuf_read() to read directly into the channel input

git+noreply at mindrot.org git+noreply at mindrot.org
Tue Jan 25 12:19:02 AEDT 2022


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit a1a8efeaaa9cccb15cdc0a2bd7c347a149a3a7e3
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Sat Jan 22 00:45:31 2022 +0000

    upstream: Use sshbuf_read() to read directly into the channel input
    
    buffer rather than into a stack buffer that needs to be copied again;
    Improves performance by about 1% on cipher-speed.sh feedback dtucker@ ok
    markus@
    
    OpenBSD-Commit-ID: bf5e6e3c821ac3546dc8241d8a94e70d47716572
---
 channels.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 9 deletions(-)

diff --git a/channels.c b/channels.c
index dbfec7c0..cceac032 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.411 2022/01/06 21:48:38 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.412 2022/01/22 00:45:31 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -1919,25 +1919,56 @@ channel_handle_rfd(struct ssh *ssh, Channel *c)
 	char buf[CHAN_RBUF];
 	ssize_t len;
 	int r, force;
+	size_t have, avail, maxlen = CHANNEL_MAX_READ;
+	int pty_zeroread = 0;
+
+#ifdef PTY_ZEROREAD
+	/* Bug on AIX: read(1) can return 0 for a non-closed fd */
+	pty_zeroread = c->isatty;
+#endif
 
 	force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
 
 	if (!force && (c->io_ready & SSH_CHAN_IO_RFD) == 0)
 		return 1;
+	if ((avail = sshbuf_avail(c->input)) == 0)
+		return 1; /* Shouldn't happen */
+
+	/*
+	 * For "simple" channels (i.e. not datagram or filtered), we can
+	 * read directly to the channel buffer.
+	 */
+	if (!pty_zeroread && c->input_filter == NULL && !c->datagram) {
+		/* Only OPEN channels have valid rwin */
+		if (c->type == SSH_CHANNEL_OPEN) {
+			if ((have = sshbuf_len(c->input)) >= c->remote_window)
+				return 1; /* shouldn't happen */
+			if (maxlen > c->remote_window - have)
+				maxlen = c->remote_window - have;
+		}
+		if (maxlen > avail)
+			maxlen = avail;
+		if ((r = sshbuf_read(c->rfd, c->input, maxlen, NULL)) != 0) {
+			debug2("channel %d: read failed rfd %d maxlen %zu: %s",
+			    c->self, c->rfd, maxlen, ssh_err(r));
+			goto rfail;
+		}
+		return 1;
+	}
 
 	errno = 0;
 	len = read(c->rfd, buf, sizeof(buf));
+	/* fixup AIX zero-length read with errno set to look more like errors */
+	if (pty_zeroread && len == 0 && errno != 0)
+		len = -1;
 	if (len == -1 && (errno == EINTR ||
 	    ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
 		return 1;
-#ifndef PTY_ZEROREAD
-	if (len <= 0) {
-#else
-	if ((!c->isatty && len <= 0) ||
-	    (c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
-#endif
-		debug2("channel %d: read<=0 rfd %d len %zd",
-		    c->self, c->rfd, len);
+	if (len < 0 || (!pty_zeroread && len == 0)) {
+		debug2("channel %d: read<=0 rfd %d len %zd: %s",
+		    c->self, c->rfd, len,
+		    len == 0 ? "closed" : strerror(errno));
+ rfail:
 		if (c->type != SSH_CHANNEL_OPEN) {
 			debug2("channel %d: not open", c->self);
 			chan_mark_dead(ssh, c);
@@ -1957,6 +1988,7 @@ channel_handle_rfd(struct ssh *ssh, Channel *c)
 			fatal_fr(r, "channel %i: put datagram", c->self);
 	} else if ((r = sshbuf_put(c->input, buf, len)) != 0)
 		fatal_fr(r, "channel %i: put data", c->self);
+
 	return 1;
 }
 

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list