[PATCH] Limit size of the iovect passed to writev in packet.c

ronny.meeus at gmail.com ronny.meeus at gmail.com
Mon May 19 14:22:19 WST 2014


The writev allows only a limited number of entries to be present in the
iovector. This number depends on the OS. If more entries are passed, the
writev operation fails and the connection is closed.

This patch limits the size of the vector to the maximum number accepted
by the OS. On some operating systems IOV_MAX is not defined, if this is
the case UIO_MAXIOV is being used as the maximum value.

In the problematic scenario the Linux box, running dropbear, has a slow
uplink. If an ssh is done to the box and a command is executed that
generates a lot of small fragments (for example a 'find .' in the root),
a lot of small interactions are seen between dropbear and the shell process.
The observation was that the amount of entries pending in the queue could
go up to 7500. Since all entries present in the queue will be passed to
writev an error will be returned since Linux only accepts 1024 entries to
be present in the vector. The result is that the connection is being closed.

Signed-off-by: Ronny Meeus <ronny.meeus at gmail.com>

diff --git a/packet.c b/packet.c
--- a/packet.c
+++ b/packet.c
@@ -64,13 +64,24 @@ void write_packet() {
 	struct iovec *iov = NULL;
 	int i;
 	struct Link *l;
+	int iov_max_count;
 #endif
 	
 	TRACE2(("enter write_packet"))
 	dropbear_assert(!isempty(&ses.writequeue));
 
 #ifdef HAVE_WRITEV
-	iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
+
+#ifndef IOV_MAX
+#define IOV_MAX UIO_MAXIOV
+#endif
+
+	/* Make sure the size of the iov is below the maximum allowed by the OS. */
+	iov_max_count = ses.writequeue.count;
+	if (iov_max_count > IOV_MAX)
+		iov_max_count = IOV_MAX;
+
+	iov = m_malloc(sizeof(*iov) * iov_max_count);
 	for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
 	{
 		writebuf = (buffer*)l->item;
@@ -83,7 +94,7 @@ void write_packet() {
 		iov[i].iov_base = buf_getptr(writebuf, len);
 		iov[i].iov_len = len;
 	}
-	written = writev(ses.sock_out, iov, ses.writequeue.count);
+	written = writev(ses.sock_out, iov, iov_max_count);
 	if (written < 0) {
 		if (errno == EINTR) {
 			m_free(iov);


More information about the Dropbear mailing list