[PATCH] cleanup around struct iovec

Volker Lendecke Volker.Lendecke at SerNet.DE
Mon Feb 23 03:52:28 MST 2015


Hi!

Attached find some cleanup patches that make use of the
iov_buf.[ch] routines we have now, among a few others.

Review&push appreciated!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 22bf001ce221228297612c440abc8174cb88b938 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 14 Feb 2015 16:28:06 +0100
Subject: [PATCH 01/13] rpc: Use tevent_req_poll_ntstatus

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 librpc/rpc/binding_handle.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/librpc/rpc/binding_handle.c b/librpc/rpc/binding_handle.c
index ef2b7bd..5a94144 100644
--- a/librpc/rpc/binding_handle.c
+++ b/librpc/rpc/binding_handle.c
@@ -250,8 +250,7 @@ NTSTATUS dcerpc_binding_handle_raw_call(struct dcerpc_binding_handle *h,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	if (!tevent_req_poll(subreq, ev)) {
-		status = map_nt_error_from_unix_common(errno);
+	if (!tevent_req_poll_ntstatus(subreq, ev, &status)) {
 		talloc_free(frame);
 		return status;
 	}
-- 
1.7.9.5


From e38ee5508c4e8c3c0bfb2864ff6452d63cb750a1 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 14 Feb 2015 16:48:54 +0100
Subject: [PATCH 02/13] lib: Move "iov_buf.[ch]" to lib/util

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/async_req/async_sock.c      |    2 +-
 lib/util/iov_buf.c              |   88 +++++++++++++++++++++++++++++++++++++++
 lib/util/iov_buf.h              |   32 ++++++++++++++
 lib/util/wscript_build          |    5 +++
 source3/lib/iov_buf.c           |   88 ---------------------------------------
 source3/lib/iov_buf.h           |   32 --------------
 source3/lib/messages.c          |    2 +-
 source3/lib/messages_ctdbd.c    |    2 +-
 source3/lib/msghdr.c            |    2 +-
 source3/lib/sys_rw_data.c       |    2 +-
 source3/lib/unix_msg/unix_msg.c |    2 +-
 source3/smbd/smb2_server.c      |    2 +-
 source3/wscript_build           |    5 ---
 13 files changed, 132 insertions(+), 132 deletions(-)
 create mode 100644 lib/util/iov_buf.c
 create mode 100644 lib/util/iov_buf.h
 delete mode 100644 source3/lib/iov_buf.c
 delete mode 100644 source3/lib/iov_buf.h

diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index b986e45..ee91b8f 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -27,7 +27,7 @@
 #include <talloc.h>
 #include <tevent.h>
 #include "lib/async_req/async_sock.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 
 /* Note: lib/util/ is currently GPL */
 #include "lib/util/tevent_unix.h"
diff --git a/lib/util/iov_buf.c b/lib/util/iov_buf.c
new file mode 100644
index 0000000..82a4af5
--- /dev/null
+++ b/lib/util/iov_buf.c
@@ -0,0 +1,88 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba system utilities
+ * Copyright (C) Volker Lendecke 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "iov_buf.h"
+
+ssize_t iov_buflen(const struct iovec *iov, int iovcnt)
+{
+	return iov_buf(iov, iovcnt, NULL, 0);
+}
+
+ssize_t iov_buf(const struct iovec *iov, int iovcnt,
+		uint8_t *buf, size_t buflen)
+{
+	size_t needed = 0;
+	uint8_t *p = buf;
+	int i;
+
+	for (i=0; i<iovcnt; i++) {
+		size_t thislen = iov[i].iov_len;
+		size_t tmp;
+
+		tmp = needed + thislen;
+
+		if (tmp < needed) {
+			/* wrap */
+			return -1;
+		}
+		needed = tmp;
+
+		if (needed <= buflen) {
+			memcpy(p, iov[i].iov_base, thislen);
+			p += thislen;
+		}
+	}
+
+	return needed;
+}
+
+bool iov_advance(struct iovec **iov, int *iovcnt, size_t n)
+{
+	struct iovec *v = *iov;
+	int cnt = *iovcnt;
+
+	while (n > 0) {
+		if (cnt == 0) {
+			return false;
+		}
+		if (n < v->iov_len) {
+			v->iov_base = (char *)v->iov_base + n;
+			v->iov_len -= n;
+			break;
+		}
+		n -= v->iov_len;
+		v += 1;
+		cnt -= 1;
+	}
+
+	/*
+	 * Skip 0-length iovec's
+	 */
+
+	while ((cnt > 0) && (v->iov_len == 0)) {
+		v += 1;
+		cnt -= 1;
+	}
+
+	*iov = v;
+	*iovcnt = cnt;
+	return true;
+}
diff --git a/lib/util/iov_buf.h b/lib/util/iov_buf.h
new file mode 100644
index 0000000..8f0ca26
--- /dev/null
+++ b/lib/util/iov_buf.h
@@ -0,0 +1,32 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba system utilities
+ * Copyright (C) Volker Lendecke 2014
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_IOV_BUF_H__
+#define __LIB_IOV_BUF_H__
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+ssize_t iov_buflen(const struct iovec *iov, int iovlen);
+ssize_t iov_buf(const struct iovec *iov, int iovcnt,
+		uint8_t *buf, size_t buflen);
+bool iov_advance(struct iovec **iov, int *iovcnt, size_t n);
+
+#endif
diff --git a/lib/util/wscript_build b/lib/util/wscript_build
index 3121e1f..2588742 100755
--- a/lib/util/wscript_build
+++ b/lib/util/wscript_build
@@ -36,6 +36,11 @@ bld.SAMBA_LIBRARY('socket-blocking',
                   local_include=False,
                   private_library=True)
 
+bld.SAMBA_LIBRARY('iov_buf',
+                  source='iov_buf.c',
+                  local_include=False,
+                  private_library=True)
+
 bld.SAMBA_SUBSYSTEM('samba-util-core',
                     source='''xfile.c data_blob.c util_file.c time.c
                               signal.c util.c idtree.c fault.c
diff --git a/source3/lib/iov_buf.c b/source3/lib/iov_buf.c
deleted file mode 100644
index 82a4af5..0000000
--- a/source3/lib/iov_buf.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Samba system utilities
- * Copyright (C) Volker Lendecke 2014
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "replace.h"
-#include "system/filesys.h"
-#include "iov_buf.h"
-
-ssize_t iov_buflen(const struct iovec *iov, int iovcnt)
-{
-	return iov_buf(iov, iovcnt, NULL, 0);
-}
-
-ssize_t iov_buf(const struct iovec *iov, int iovcnt,
-		uint8_t *buf, size_t buflen)
-{
-	size_t needed = 0;
-	uint8_t *p = buf;
-	int i;
-
-	for (i=0; i<iovcnt; i++) {
-		size_t thislen = iov[i].iov_len;
-		size_t tmp;
-
-		tmp = needed + thislen;
-
-		if (tmp < needed) {
-			/* wrap */
-			return -1;
-		}
-		needed = tmp;
-
-		if (needed <= buflen) {
-			memcpy(p, iov[i].iov_base, thislen);
-			p += thislen;
-		}
-	}
-
-	return needed;
-}
-
-bool iov_advance(struct iovec **iov, int *iovcnt, size_t n)
-{
-	struct iovec *v = *iov;
-	int cnt = *iovcnt;
-
-	while (n > 0) {
-		if (cnt == 0) {
-			return false;
-		}
-		if (n < v->iov_len) {
-			v->iov_base = (char *)v->iov_base + n;
-			v->iov_len -= n;
-			break;
-		}
-		n -= v->iov_len;
-		v += 1;
-		cnt -= 1;
-	}
-
-	/*
-	 * Skip 0-length iovec's
-	 */
-
-	while ((cnt > 0) && (v->iov_len == 0)) {
-		v += 1;
-		cnt -= 1;
-	}
-
-	*iov = v;
-	*iovcnt = cnt;
-	return true;
-}
diff --git a/source3/lib/iov_buf.h b/source3/lib/iov_buf.h
deleted file mode 100644
index 8f0ca26..0000000
--- a/source3/lib/iov_buf.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Unix SMB/CIFS implementation.
- * Samba system utilities
- * Copyright (C) Volker Lendecke 2014
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __LIB_IOV_BUF_H__
-#define __LIB_IOV_BUF_H__
-
-#include <unistd.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-ssize_t iov_buflen(const struct iovec *iov, int iovlen);
-ssize_t iov_buf(const struct iovec *iov, int iovcnt,
-		uint8_t *buf, size_t buflen);
-bool iov_advance(struct iovec **iov, int *iovcnt, size_t n);
-
-#endif
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 7df7cdb..aa67640 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -52,7 +52,7 @@
 #include "lib/util/tevent_unix.h"
 #include "lib/background.h"
 #include "lib/messages_dgm.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 #include "lib/util/server_id_db.h"
 #include "lib/messages_dgm_ref.h"
 #include "lib/messages_util.h"
diff --git a/source3/lib/messages_ctdbd.c b/source3/lib/messages_ctdbd.c
index dbca103..1268bd4 100644
--- a/source3/lib/messages_ctdbd.c
+++ b/source3/lib/messages_ctdbd.c
@@ -20,7 +20,7 @@
 #include "includes.h"
 #include "messages.h"
 #include "util_tdb.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 
 /*
  * It is not possible to include ctdb.h and tdb_compat.h (included via
diff --git a/source3/lib/msghdr.c b/source3/lib/msghdr.c
index 82f7ca7..5d771e8 100644
--- a/source3/lib/msghdr.c
+++ b/source3/lib/msghdr.c
@@ -18,7 +18,7 @@
 
 #include "replace.h"
 #include "lib/msghdr.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 #include <sys/socket.h>
 
 ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
diff --git a/source3/lib/sys_rw_data.c b/source3/lib/sys_rw_data.c
index 7198783..e3f934d 100644
--- a/source3/lib/sys_rw_data.c
+++ b/source3/lib/sys_rw_data.c
@@ -24,7 +24,7 @@
 #include "system/filesys.h"
 #include "lib/sys_rw_data.h"
 #include "lib/sys_rw.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 
 /****************************************************************************
  Write all data from an iov array
diff --git a/source3/lib/unix_msg/unix_msg.c b/source3/lib/unix_msg/unix_msg.c
index 6714f0d..f242249 100644
--- a/source3/lib/unix_msg/unix_msg.c
+++ b/source3/lib/unix_msg/unix_msg.c
@@ -23,7 +23,7 @@
 #include "system/network.h"
 #include "dlinklist.h"
 #include "pthreadpool/pthreadpool.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 #include "lib/msghdr.h"
 #include <fcntl.h>
 
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 25d11b1..0113378 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -28,7 +28,7 @@
 #include "smbprofile.h"
 #include "../lib/util/bitmap.h"
 #include "../librpc/gen_ndr/krb5pac.h"
-#include "lib/iov_buf.h"
+#include "lib/util/iov_buf.h"
 #include "auth.h"
 
 static void smbd_smb2_connection_handler(struct tevent_context *ev,
diff --git a/source3/wscript_build b/source3/wscript_build
index d166d4e..24cf06c 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -252,11 +252,6 @@ bld.SAMBA3_LIBRARY('sys_rw',
                    deps='replace iov_buf',
                    private_library=True)
 
-bld.SAMBA3_LIBRARY('iov_buf',
-                   source='lib/iov_buf.c',
-                   deps='replace',
-                   private_library=True)
-
 bld.SAMBA3_SUBSYSTEM('samba3util',
                    source='''lib/system.c
                    lib/sendfile.c
-- 
1.7.9.5


From d55446860e56b50b686cb2c5db11c772f614bdd6 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 13:24:04 +0000
Subject: [PATCH 03/13] tsocket: Fix a typo

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tsocket/tsocket_bsd.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index fe39dfd..35fd089 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -1117,7 +1117,7 @@ static void tdgram_bsd_sendto_handler(void *private_data)
 				 sizeof(bufsize));
 		if (ret == 0) {
 			/*
-			 * We do the rety here, rather then via the
+			 * We do the retry here, rather then via the
 			 * handler, as we only want to retry once for
 			 * this condition, so if there is a mismatch
 			 * between what setsockopt() accepts and what can
-- 
1.7.9.5


From e73c8c74f31fa2debd2f7e6596b0616d947b5d56 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 13:26:29 +0000
Subject: [PATCH 04/13] iov_buf: Add an explaining comment

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/util/iov_buf.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/util/iov_buf.c b/lib/util/iov_buf.c
index 82a4af5..fcdba0a 100644
--- a/lib/util/iov_buf.c
+++ b/lib/util/iov_buf.c
@@ -75,6 +75,10 @@ bool iov_advance(struct iovec **iov, int *iovcnt, size_t n)
 
 	/*
 	 * Skip 0-length iovec's
+	 *
+	 * There might be empty buffers at the end of iov. Next time we do a
+	 * readv/writev based on this iov would give 0 transferred bytes, also
+	 * known as EPIPE. So we need to be careful discardind them.
 	 */
 
 	while ((cnt > 0) && (v->iov_len == 0)) {
-- 
1.7.9.5


From e79691a8aa39c85a367095ef27e4730853102f52 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 13:50:25 +0000
Subject: [PATCH 05/13] tsocket: Use iov_advance

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tsocket/tsocket_bsd.c |   67 ++++++++++++---------------------------------
 lib/tsocket/wscript_build |    2 +-
 2 files changed, 18 insertions(+), 51 deletions(-)

diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index 35fd089..79235c6 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -26,6 +26,7 @@
 #include "system/network.h"
 #include "tsocket.h"
 #include "tsocket_internal.h"
+#include "lib/util/iov_buf.h"
 
 static int tsocket_bsd_error_from_errno(int ret,
 					int sys_errno,
@@ -1747,7 +1748,8 @@ static void tstream_bsd_readv_handler(void *private_data)
 	struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
 	int ret;
 	int err;
-	bool retry;
+	int _count;
+	bool ok, retry;
 
 	ret = readv(bsds->fd, state->vector, state->count);
 	if (ret == 0) {
@@ -1766,31 +1768,13 @@ static void tstream_bsd_readv_handler(void *private_data)
 
 	state->ret += ret;
 
-	while (ret > 0) {
-		if (ret < state->vector[0].iov_len) {
-			uint8_t *base;
-			base = (uint8_t *)state->vector[0].iov_base;
-			base += ret;
-			state->vector[0].iov_base = (void *)base;
-			state->vector[0].iov_len -= ret;
-			break;
-		}
-		ret -= state->vector[0].iov_len;
-		state->vector += 1;
-		state->count -= 1;
-	}
+	_count = state->count; /* tstream has size_t count, readv has int */
+	ok = iov_advance(&state->vector, &_count, ret);
+	state->count = _count;
 
-	/*
-	 * there're maybe some empty vectors at the end
-	 * which we need to skip, otherwise we would get
-	 * ret == 0 from the readv() call and return EPIPE
-	 */
-	while (state->count > 0) {
-		if (state->vector[0].iov_len > 0) {
-			break;
-		}
-		state->vector += 1;
-		state->count -= 1;
+	if (!ok) {
+		tevent_req_error(req, EINVAL);
+		return;
 	}
 
 	if (state->count > 0) {
@@ -1907,7 +1891,8 @@ static void tstream_bsd_writev_handler(void *private_data)
 	struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
 	ssize_t ret;
 	int err;
-	bool retry;
+	int _count;
+	bool ok, retry;
 
 	ret = writev(bsds->fd, state->vector, state->count);
 	if (ret == 0) {
@@ -1926,31 +1911,13 @@ static void tstream_bsd_writev_handler(void *private_data)
 
 	state->ret += ret;
 
-	while (ret > 0) {
-		if (ret < state->vector[0].iov_len) {
-			uint8_t *base;
-			base = (uint8_t *)state->vector[0].iov_base;
-			base += ret;
-			state->vector[0].iov_base = (void *)base;
-			state->vector[0].iov_len -= ret;
-			break;
-		}
-		ret -= state->vector[0].iov_len;
-		state->vector += 1;
-		state->count -= 1;
-	}
+	_count = state->count; /* tstream has size_t count, writev has int */
+	ok = iov_advance(&state->vector, &_count, ret);
+	state->count = _count;
 
-	/*
-	 * there're maybe some empty vectors at the end
-	 * which we need to skip, otherwise we would get
-	 * ret == 0 from the writev() call and return EPIPE
-	 */
-	while (state->count > 0) {
-		if (state->vector[0].iov_len > 0) {
-			break;
-		}
-		state->vector += 1;
-		state->count -= 1;
+	if (!ok) {
+		tevent_req_error(req, EINVAL);
+		return;
 	}
 
 	if (state->count > 0) {
diff --git a/lib/tsocket/wscript_build b/lib/tsocket/wscript_build
index 5fa05f8..31ef14e 100644
--- a/lib/tsocket/wscript_build
+++ b/lib/tsocket/wscript_build
@@ -3,7 +3,7 @@
 
 bld.SAMBA_SUBSYSTEM('LIBTSOCKET',
 	source='tsocket.c tsocket_helpers.c tsocket_bsd.c',
-	public_deps='talloc tevent',
+	public_deps='talloc tevent iov_buf',
 	public_headers='tsocket.h tsocket_internal.h',
 	)
 
-- 
1.7.9.5


From ece340273640891e1b8d728d5e938eb3c9b46994 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 14:29:36 +0000
Subject: [PATCH 06/13] smb2_server: Add range checking to nbt_length

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_server.c |   61 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 48 insertions(+), 13 deletions(-)

diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 0113378..5c1fa98 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -237,16 +237,22 @@ static NTSTATUS smbd_initialize_smb2(struct smbXsrv_connection *xconn)
 	buf[3] = (len)&0xFF; \
 } while (0)
 
-static void smb2_setup_nbt_length(struct iovec *vector, int count)
+static bool smb2_setup_nbt_length(struct iovec *vector, int count)
 {
-	size_t len = 0;
-	int i;
+	ssize_t len;
+
+	if (count == 0) {
+		return false;
+	}
 
-	for (i=1; i < count; i++) {
-		len += vector[i].iov_len;
+	len = iov_buflen(vector+1, count-1);
+
+	if ((len == -1) || (len > 0xFFFFFF)) {
+		return false;
 	}
 
 	_smb2_setlen(vector[0].iov_base, len);
+	return true;
 }
 
 static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
@@ -944,6 +950,7 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 	struct iovec *vector;
 	int count;
 	int idx;
+	bool ok;
 
 	count = req->in.vector_count;
 	if (count <= ARRAY_SIZE(req->out._vector)) {
@@ -1035,7 +1042,10 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
 	req->out.vector_count = count;
 
 	/* setup the length of the NBT packet */
-	smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
+	ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
+	if (!ok) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
 
 	DLIST_ADD_END(xconn->smb2.requests, req, struct smbd_smb2_request *);
 
@@ -1156,6 +1166,7 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
 	struct iovec *outvec = NULL;
 	int count = req->out.vector_count;
 	int i;
+	bool ok;
 
 	newreq = smbd_smb2_request_allocate(req->xconn);
 	if (!newreq) {
@@ -1195,8 +1206,12 @@ static struct smbd_smb2_request *dup_smb2_req(const struct smbd_smb2_request *re
 		return NULL;
 	}
 
-	smb2_setup_nbt_length(newreq->out.vector,
-		newreq->out.vector_count);
+	ok = smb2_setup_nbt_length(newreq->out.vector,
+				   newreq->out.vector_count);
+	if (!ok) {
+		TALLOC_FREE(newreq);
+		return NULL;
+	}
 
 	return newreq;
 }
@@ -1210,6 +1225,7 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
 	uint8_t *outhdr = NULL;
 	struct smbd_smb2_request *nreq = NULL;
 	NTSTATUS status;
+	bool ok;
 
 	/* Create a new smb2 request we'll use
 	   for the interim return. */
@@ -1222,8 +1238,11 @@ static NTSTATUS smb2_send_async_interim_response(const struct smbd_smb2_request
 	   ones we'll be using for the async reply. */
 	nreq->out.vector_count -= SMBD_SMB2_NUM_IOV_PER_REQ;
 
-	smb2_setup_nbt_length(nreq->out.vector,
-		nreq->out.vector_count);
+	ok = smb2_setup_nbt_length(nreq->out.vector,
+				   nreq->out.vector_count);
+	if (!ok) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
 
 	/* Step back to the previous reply. */
 	nreq->current_idx -= SMBD_SMB2_NUM_IOV_PER_REQ;
@@ -1463,6 +1482,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
 	uint64_t nonce_low = 0;
 	uint64_t async_id = 0;
 	NTSTATUS status;
+	bool ok;
 
 	TALLOC_FREE(req->async_te);
 
@@ -1564,7 +1584,13 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
 	state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_base  = dyn;
 	state->vector[1+SMBD_SMB2_DYN_IOV_OFS].iov_len   = 1;
 
-	smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
+	ok = smb2_setup_nbt_length(state->vector,
+				   1 + SMBD_SMB2_NUM_IOV_PER_REQ);
+	if (!ok) {
+		smbd_server_connection_terminate(
+			xconn, nt_errstr(NT_STATUS_INTERNAL_ERROR));
+		return;
+	}
 
 	/* Ensure we correctly go through crediting. Grant
 	   the credits now, and zero credits on the final
@@ -2326,6 +2352,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 	struct iovec *outhdr = SMBD_SMB2_OUT_HDR_IOV(req);
 	struct iovec *outdyn = SMBD_SMB2_OUT_DYN_IOV(req);
 	NTSTATUS status;
+	bool ok;
 
 	req->subreq = NULL;
 	TALLOC_FREE(req->async_te);
@@ -2453,7 +2480,10 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
 		req->compound_related = false;
 	}
 
-	smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
+	ok = smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
+	if (!ok) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
 
 	/* Set credit for these operations (zero credits if this
 	   is a final reply for an async operation). */
@@ -2736,6 +2766,7 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
 	uint64_t nonce_low = 0;
 	NTSTATUS status;
 	size_t statelen;
+	bool ok;
 
 	if (session != NULL) {
 		session_wire_id = session->global->session_wire_id;
@@ -2817,7 +2848,11 @@ static NTSTATUS smbd_smb2_send_break(struct smbXsrv_connection *xconn,
 	 * state->vector[1+SMBD_SMB2_DYN_IOV_OFS] is NULL by talloc_zero above
 	 */
 
-	smb2_setup_nbt_length(state->vector, 1 + SMBD_SMB2_NUM_IOV_PER_REQ);
+	ok = smb2_setup_nbt_length(state->vector,
+				   1 + SMBD_SMB2_NUM_IOV_PER_REQ);
+	if (!ok) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
 
 	if (do_encryption) {
 		DATA_BLOB encryption_key = session->global->encryption_key;
-- 
1.7.9.5


From aa680d2d1815d722dd974b6ca410cca95407855e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 14:35:03 +0000
Subject: [PATCH 07/13] smb2_server: Use iov_advance

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_server.c |   28 ++++------------------------
 1 file changed, 4 insertions(+), 24 deletions(-)

diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 5c1fa98..432b866 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -3173,6 +3173,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
 
 	while (xconn->smb2.send_queue != NULL) {
 		struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
+		bool ok;
 
 		if (e->sendfile_header != NULL) {
 			NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
@@ -3234,31 +3235,10 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
 		if (err != 0) {
 			return map_nt_error_from_unix_common(err);
 		}
-		while (ret > 0) {
-			if (ret < e->vector[0].iov_len) {
-				uint8_t *base;
-				base = (uint8_t *)e->vector[0].iov_base;
-				base += ret;
-				e->vector[0].iov_base = (void *)base;
-				e->vector[0].iov_len -= ret;
-				break;
-			}
-			ret -= e->vector[0].iov_len;
-			e->vector += 1;
-			e->count -= 1;
-		}
 
-		/*
-		 * there're maybe some empty vectors at the end
-		 * which we need to skip, otherwise we would get
-		 * ret == 0 from the readv() call and return EPIPE
-		 */
-		while (e->count > 0) {
-			if (e->vector[0].iov_len > 0) {
-				break;
-			}
-			e->vector += 1;
-			e->count -= 1;
+		ok = iov_advance(&e->vector, &e->count, ret);
+		if (!ok) {
+			return NT_STATUS_INTERNAL_ERROR;
 		}
 
 		if (e->count > 0) {
-- 
1.7.9.5


From 0ae7f14b3bd06ee9889343a7c2c3ab1baef3e2cc Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 16 Feb 2015 14:36:28 +0000
Subject: [PATCH 08/13] smbd: Fix a typo

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/trans2.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index c70ca2c..bdad126 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -4031,7 +4031,7 @@ static void call_trans2setfsinfo(connection_struct *conn,
 					return;
 				}
 
-				/* note: normaly there're 48 bytes,
+				/* note: normally there're 48 bytes,
 				 * but we didn't use the last 6 bytes for now 
 				 * --metze 
 				 */
-- 
1.7.9.5


From d3a59850c544659e187417a0c6154578623ac21b Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 17 Feb 2015 20:16:45 +0000
Subject: [PATCH 09/13] libcli: Use iov_buflen in smbXcli_iov_len

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |   11 +++++------
 libcli/smb/wscript        |    2 +-
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 8aa6020..f8d4df3 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -25,6 +25,7 @@
 #include "../lib/util/tevent_unix.h"
 #include "lib/util/util_net.h"
 #include "lib/util/dlinklist.h"
+#include "lib/util/iov_buf.h"
 #include "../libcli/smb/smb_common.h"
 #include "../libcli/smb/smb_seal.h"
 #include "../libcli/smb/smb_signing.h"
@@ -1115,12 +1116,10 @@ void smb1cli_req_set_seqnum(struct tevent_req *req, uint32_t seqnum)
 
 static size_t smbXcli_iov_len(const struct iovec *iov, int count)
 {
-	size_t result = 0;
-	int i;
-	for (i=0; i<count; i++) {
-		result += iov[i].iov_len;
-	}
-	return result;
+	ssize_t ret = iov_buflen(iov, count);
+
+	/* Ignore the overflow case for now ... */
+	return ret;
 }
 
 static uint8_t *smbXcli_iov_concat(TALLOC_CTX *mem_ctx,
diff --git a/libcli/smb/wscript b/libcli/smb/wscript
index 48fa2b4..dad9821 100755
--- a/libcli/smb/wscript
+++ b/libcli/smb/wscript
@@ -46,7 +46,7 @@ def build(bld):
                 LIBCRYPTO NDR_SMB2_LEASE_STRUCT errors gensec krb5samba
                 smb_transport
         ''',
-	public_deps='talloc samba-util',
+	public_deps='talloc samba-util iov_buf',
 	private_library=True,
 	public_headers='''
 		smb_common.h smb2_constants.h smb_constants.h
-- 
1.7.9.5


From 3bb4c53304e37231c7a5a97393b4e327ed9ed986 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 17 Feb 2015 20:17:35 +0000
Subject: [PATCH 10/13] lib: Use iov_buf in smbXcli_iov_concat

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |   19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index f8d4df3..b9c3c8b 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -1126,20 +1126,21 @@ static uint8_t *smbXcli_iov_concat(TALLOC_CTX *mem_ctx,
 				   const struct iovec *iov,
 				   int count)
 {
-	size_t len = smbXcli_iov_len(iov, count);
-	size_t copied;
+	ssize_t buflen;
 	uint8_t *buf;
-	int i;
 
-	buf = talloc_array(mem_ctx, uint8_t, len);
-	if (buf == NULL) {
+	buflen = iov_buflen(iov, count);
+	if (buflen == -1) {
 		return NULL;
 	}
-	copied = 0;
-	for (i=0; i<count; i++) {
-		memcpy(buf+copied, iov[i].iov_base, iov[i].iov_len);
-		copied += iov[i].iov_len;
+
+	buf = talloc_array(mem_ctx, uint8_t, buflen);
+	if (buf == NULL) {
+		return NULL;
 	}
+
+	iov_buf(iov, count, buf, buflen);
+
 	return buf;
 }
 
-- 
1.7.9.5


From 08eb48b242f618b98aeea0c39596a8e6b9abcc0a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 17 Feb 2015 20:18:37 +0000
Subject: [PATCH 11/13] lib: Use iov_buflen in smb1cli_req_create

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index b9c3c8b..ba00e96 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -1266,6 +1266,7 @@ struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
 	uint16_t flags2 = 0;
 	uint16_t uid = 0;
 	uint16_t tid = 0;
+	ssize_t num_bytes;
 
 	if (iov_count > MAX_SMB_IOV) {
 		/*
@@ -1337,7 +1338,17 @@ struct tevent_req *smb1cli_req_create(TALLOC_CTX *mem_ctx,
 
 	state->smb1.vwv = vwv;
 
-	SSVAL(state->smb1.bytecount_buf, 0, smbXcli_iov_len(bytes_iov, iov_count));
+	num_bytes = iov_buflen(bytes_iov, iov_count);
+	if (num_bytes == -1) {
+		/*
+		 * I'd love to add a check for num_bytes<=UINT16_MAX here, but
+		 * the smbclient->samba connections can lie and transfer more.
+		 */
+		TALLOC_FREE(req);
+		return NULL;
+	}
+
+	SSVAL(state->smb1.bytecount_buf, 0, num_bytes);
 
 	state->smb1.iov[0].iov_base = (void *)state->length_hdr;
 	state->smb1.iov[0].iov_len  = sizeof(state->length_hdr);
-- 
1.7.9.5


From 6c17c99da8814497e38fb0e7dd263457319f0441 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 17 Feb 2015 20:19:10 +0000
Subject: [PATCH 12/13] lib: Use iov_buflen in smb1cli_req_writev_submit

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index ba00e96..f221045 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -1455,6 +1455,7 @@ static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
 	NTSTATUS status;
 	uint8_t cmd;
 	uint16_t mid;
+	ssize_t nbtlen;
 
 	if (!smbXcli_conn_is_connected(state->conn)) {
 		return NT_STATUS_CONNECTION_DISCONNECTED;
@@ -1495,7 +1496,12 @@ static NTSTATUS smb1cli_req_writev_submit(struct tevent_req *req,
 	}
 	SSVAL(iov[1].iov_base, HDR_MID, mid);
 
-	_smb_setlen_nbt(iov[0].iov_base, smbXcli_iov_len(&iov[1], iov_count-1));
+	nbtlen = iov_buflen(&iov[1], iov_count-1);
+	if ((nbtlen == -1) || (nbtlen > 0x1FFFF)) {
+		return NT_STATUS_INVALID_PARAMETER_MIX;
+	}
+
+	_smb_setlen_nbt(iov[0].iov_base, nbtlen);
 
 	status = smb1cli_conn_signv(state->conn, iov, iov_count,
 				    &state->smb1.seqnum,
-- 
1.7.9.5


From fcaf21e93a38de1b207315cb1647a2d95303c82a Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Tue, 17 Feb 2015 20:19:33 +0000
Subject: [PATCH 13/13] lib: Use iov_buflen in smb1cli_req_chain_submit

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 libcli/smb/smbXcli_base.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index f221045..2b34980 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -2367,7 +2367,7 @@ NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
 	struct iovec *iov = NULL;
 	struct iovec *this_iov;
 	NTSTATUS status;
-	size_t nbt_len;
+	ssize_t nbt_len;
 
 	if (num_reqs == 1) {
 		return smb1cli_req_writev_submit(reqs[0], first_state,
@@ -2489,8 +2489,8 @@ NTSTATUS smb1cli_req_chain_submit(struct tevent_req **reqs, int num_reqs)
 		chain_padding = next_padding;
 	}
 
-	nbt_len = smbXcli_iov_len(&iov[1], iovlen-1);
-	if (nbt_len > first_state->conn->smb1.max_xmit) {
+	nbt_len = iov_buflen(&iov[1], iovlen-1);
+	if ((nbt_len == -1) || (nbt_len > first_state->conn->smb1.max_xmit)) {
 		TALLOC_FREE(iov);
 		TALLOC_FREE(first_state->smb1.chained_requests);
 		return NT_STATUS_INVALID_PARAMETER_MIX;
-- 
1.7.9.5



More information about the samba-technical mailing list