[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