summaryrefslogtreecommitdiffstats
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/globals.h1
-rw-r--r--source3/smbd/smb2_server.c43
2 files changed, 31 insertions, 13 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index bae3ed03ae2..2b7fc7ec51c 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -586,6 +586,7 @@ struct smbd_smb2_request {
*/
struct iovec *vector;
int vector_count;
+ struct iovec _vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ];
} in;
struct {
/* the NBT header is not allocated */
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 5e6bfd95cac..192e99c8147 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -297,10 +297,11 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
NTTIME now,
uint8_t *buf,
size_t buflen,
- TALLOC_CTX *mem_ctx,
+ struct smbd_smb2_request *req,
struct iovec **piov,
int *pnum_iov)
{
+ TALLOC_CTX *mem_ctx = req;
struct iovec *iov;
int num_iov = 1;
size_t taken = 0;
@@ -312,10 +313,7 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
/*
* Note: index '0' is reserved for the transport protocol
*/
- iov = talloc_zero_array(mem_ctx, struct iovec, num_iov);
- if (iov == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ iov = req->in._vector;
while (taken < buflen) {
size_t len = buflen - taken;
@@ -327,7 +325,6 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
uint8_t *body = NULL;
uint32_t dyn_size;
uint8_t *dyn = NULL;
- struct iovec *iov_tmp;
if (verified_buflen > taken) {
len = verified_buflen - taken;
@@ -458,13 +455,31 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
dyn = body + body_size;
dyn_size = full_size - (SMB2_HDR_BODY + body_size);
- iov_tmp = talloc_realloc(mem_ctx, iov, struct iovec,
- num_iov + SMBD_SMB2_NUM_IOV_PER_REQ);
- if (iov_tmp == NULL) {
- TALLOC_FREE(iov);
- return NT_STATUS_NO_MEMORY;
+ if (num_iov >= ARRAY_SIZE(req->in._vector)) {
+ struct iovec *iov_tmp = NULL;
+ struct iovec *iov_alloc = NULL;
+
+ if (iov != req->in._vector) {
+ iov_alloc = iov;
+ }
+
+ iov_tmp = talloc_realloc(mem_ctx, iov_alloc,
+ struct iovec,
+ num_iov +
+ SMBD_SMB2_NUM_IOV_PER_REQ);
+ if (iov_tmp == NULL) {
+ TALLOC_FREE(iov_alloc);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (iov_alloc == NULL) {
+ memcpy(iov_tmp,
+ req->in._vector,
+ sizeof(req->in._vector));
+ }
+
+ iov = iov_tmp;
}
- iov = iov_tmp;
cur = &iov[num_iov];
num_iov += SMBD_SMB2_NUM_IOV_PER_REQ;
@@ -485,7 +500,9 @@ static NTSTATUS smbd_smb2_inbuf_parse_compound(struct smbXsrv_connection *conn,
return NT_STATUS_OK;
inval:
- TALLOC_FREE(iov);
+ if (iov != req->in._vector) {
+ TALLOC_FREE(iov);
+ }
return NT_STATUS_INVALID_PARAMETER;
}