remote vs local window discrepancy

Damien Miller djm at mindrot.org
Wed Jul 28 11:16:56 EST 2010


On Tue, 27 Jul 2010, David Wierbowski wrote:

> Damien,
> 
> I tried the change below.  This appears to take care of the issue with the
> remote_window being decremented by a value that is off by 4.
> Unfortunately, now the local_window is growing by a value of 4,  It seems
> that local_window is being decremented by 4 bytes less than local_consumed.

Ok, please remove the previous diff and try this one. It changes the way
that local_consumed is calculated to be more simple and robust against
fiddling with lengths inside channel_handle_wrd()

Index: channels.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/channels.c,v
retrieving revision 1.308
diff -u -p -r1.308 channels.c
--- channels.c	13 Jul 2010 23:13:16 -0000	1.308
+++ channels.c	28 Jul 2010 01:14:18 -0000
@@ -1632,13 +1632,14 @@ channel_handle_wfd(Channel *c, fd_set *r
 {
 	struct termios tio;
 	u_char *data = NULL, *buf;
-	u_int dlen;
+	u_int dlen, olen = 0;
 	int len;
 
 	/* Send buffered output data to the socket. */
 	if (c->wfd != -1 &&
 	    FD_ISSET(c->wfd, writeset) &&
 	    buffer_len(&c->output) > 0) {
+		olen = buffer_len(&c->output);
 		if (c->output_filter != NULL) {
 			if ((buf = c->output_filter(c, &data, &dlen)) == NULL) {
 				debug2("channel %d: filter stops", c->self);
@@ -1657,7 +1658,6 @@ channel_handle_wfd(Channel *c, fd_set *r
 
 		if (c->datagram) {
 			/* ignore truncated writes, datagrams might get lost */
-			c->local_consumed += dlen + 4;
 			len = write(c->wfd, buf, dlen);
 			xfree(data);
 			if (len < 0 && (errno == EINTR || errno == EAGAIN))
@@ -1669,7 +1669,7 @@ channel_handle_wfd(Channel *c, fd_set *r
 					chan_write_failed(c);
 				return -1;
 			}
-			return 1;
+			goto out;
 		}
 
 		len = write(c->wfd, buf, dlen);
@@ -1703,10 +1703,10 @@ channel_handle_wfd(Channel *c, fd_set *r
 			}
 		}
 		buffer_consume(&c->output, len);
-		if (compat20 && len > 0) {
-			c->local_consumed += len;
-		}
 	}
+ out:
+	if (compat20 && olen > 0)
+		c->local_consumed += olen - buffer_len(&c->output);
 	return 1;
 }
 
@@ -2150,6 +2150,14 @@ channel_output_poll(void)
 
 					data = buffer_get_string(&c->input,
 					    &dlen);
+					if (dlen > c->remote_window ||
+					    dlen > c->remote_maxpacket) {
+						debug("channel %d: datagram "
+						    "too big for channel",
+						    c->self);
+						xfree(data);
+						continue;
+					}
 					packet_start(SSH2_MSG_CHANNEL_DATA);
 					packet_put_int(c->remote_id);
 					packet_put_string(data, dlen);


More information about the openssh-unix-dev mailing list