>From 4df975f64415cbb892899302c21aad7fe4d6e131 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 19 Nov 2013 07:42:57 +0100 Subject: [PATCH 01/25] s3:smb2_server: optimize req->in.vector allocation We can avoid a talloc_zero_array() call in the common case (without compound requests) and use a preallocated array instead. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 1 + source3/smbd/smb2_server.c | 43 ++++++++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index bae3ed0..2b7fc7e 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 5e6bfd9..192e99c 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; } -- 1.7.9.5 >From 409155a31954d7b4eb9fe94c4fb92f64cb78a1af Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Nov 2013 09:56:19 +0100 Subject: [PATCH 02/25] s3:smb2_server: optimize smbd_smb2_request_setup_out() We can use a preallocated buffer for the possible error response of the first response in the compound chain. This avoids a talloc_array_zero() call for the common case. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 2 ++ source3/smbd/smb2_server.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 2b7fc7e..781379c 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -611,6 +611,8 @@ struct smbd_smb2_request { */ struct iovec *vector; int vector_count; +#define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9) + uint8_t _hdr[OUTVEC_ALLOC_SIZE]; } out; }; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 192e99c..c987662 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -37,8 +37,6 @@ static void smbd_smb2_connection_handler(struct tevent_context *ev, static NTSTATUS smbd_smb2_io_handler(struct smbd_server_connection *sconn, uint16_t fde_flags); -#define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9) - static const struct smbd_smb2_dispatch_table { uint16_t opcode; const char *name; @@ -948,10 +946,14 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) next_command_ofs = SMB2_HDR_BODY + 9; } - outhdr = talloc_zero_array(vector, uint8_t, - OUTVEC_ALLOC_SIZE); - if (outhdr == NULL) { - return NT_STATUS_NO_MEMORY; + if (idx == 1) { + outhdr = req->out._hdr; + } else { + outhdr = talloc_zero_array(vector, uint8_t, + OUTVEC_ALLOC_SIZE); + if (outhdr == NULL) { + return NT_STATUS_NO_MEMORY; + } } outbody = outhdr + SMB2_HDR_BODY; -- 1.7.9.5 >From 0f6d1f7dfac3d3f1b9f80fd106af0a1d6d3a4d97 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Nov 2013 09:56:48 +0100 Subject: [PATCH 03/25] s3:smb2_server: avoid a call to data_blob_clear_free() if not needed Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_server.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index c987662..dea3915 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -253,8 +253,12 @@ static void smb2_setup_nbt_length(struct iovec *vector, int count) static int smbd_smb2_request_destructor(struct smbd_smb2_request *req) { - data_blob_clear_free(&req->first_key); - data_blob_clear_free(&req->last_key); + if (req->first_key.length > 0) { + data_blob_clear_free(&req->first_key); + } + if (req->last_key.length > 0) { + data_blob_clear_free(&req->last_key); + } return 0; } @@ -1343,7 +1347,9 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, if (!NT_STATUS_IS_OK(status)) { return status; } - data_blob_clear_free(&req->first_key); + if (req->first_key.length > 0) { + data_blob_clear_free(&req->first_key); + } req->current_idx = 1; @@ -1374,7 +1380,9 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, SIVAL(outhdr, SMB2_HDR_FLAGS, flags); } } - data_blob_clear_free(&req->last_key); + if (req->last_key.length > 0) { + data_blob_clear_free(&req->last_key); + } defer_endtime = timeval_current_ofs_usec(defer_time); req->async_te = tevent_add_timer(req->sconn->ev_ctx, @@ -2364,7 +2372,9 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) return status; } } - data_blob_clear_free(&req->last_key); + if (req->last_key.length > 0) { + data_blob_clear_free(&req->last_key); + } req->current_idx += SMBD_SMB2_NUM_IOV_PER_REQ; @@ -2438,7 +2448,9 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) return status; } } - data_blob_clear_free(&req->first_key); + if (req->first_key.length > 0) { + data_blob_clear_free(&req->first_key); + } /* I am a sick, sick man... :-). Sendfile hack ... JRA. */ if (req->out.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) && -- 1.7.9.5 >From edee27c3ec2329cb549828617b0c51377211ebf6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 12:32:36 +0100 Subject: [PATCH 04/25] s3:smb2_read: avoid 2 talloc* calls when using sendfile() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_read.c | 30 ++++++++++++++++++------------ source3/smbd/smb2_server.c | 14 +++++++++++--- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 6478326..474eaea 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -167,10 +167,16 @@ struct smbd_smb2_read_state { uint64_t in_offset; uint32_t in_minimum; DATA_BLOB out_headers; + uint8_t _out_hdr_buf[NBT_HDR_SIZE + SMB2_HDR_BODY + 0x10]; DATA_BLOB out_data; uint32_t out_remaining; }; +static int smb2_smb2_read_state_deny_destructor(struct smbd_smb2_read_state *state) +{ + return -1; +} + /* struct smbd_smb2_read_state destructor. Send the SMB2_READ data. */ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state) { @@ -258,7 +264,6 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state) static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req, struct smbd_smb2_read_state *state) { - struct smbd_smb2_read_state *state_copy = NULL; files_struct *fsp = state->fsp; /* @@ -293,16 +298,8 @@ static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req, state->out_data.length = state->in_length; state->out_remaining = 0; - /* Make a copy of state attached to the smb2req. Attach - the destructor here as this will trigger the sendfile - call when the request is destroyed. */ - state_copy = talloc(smb2req, struct smbd_smb2_read_state); - if (!state_copy) { - return NT_STATUS_NO_MEMORY; - } - *state_copy = *state; - talloc_set_destructor(state_copy, smb2_sendfile_send_data); - state->smb2req->queue_entry.sendfile_header = &state_copy->out_headers; + state->out_headers = data_blob_const(state->_out_hdr_buf, + sizeof(state->_out_hdr_buf)); return NT_STATUS_OK; } @@ -582,6 +579,15 @@ static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req, talloc_steal(mem_ctx, out_data->data); *out_remaining = state->out_remaining; - tevent_req_received(req); + if (state->out_headers.length > 0) { + talloc_steal(mem_ctx, state); + talloc_set_destructor(state, smb2_smb2_read_state_deny_destructor); + tevent_req_received(req); + state->smb2req->queue_entry.sendfile_header = &state->out_headers; + talloc_set_destructor(state, smb2_sendfile_send_data); + } else { + tevent_req_received(req); + } + return NT_STATUS_OK; } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index dea3915..b805c1a 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -3035,9 +3035,13 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) size += e->vector[i].iov_len; } - buf = talloc_array(e->mem_ctx, uint8_t, size); - if (buf == NULL) { - return NT_STATUS_NO_MEMORY; + if (size <= e->sendfile_header->length) { + buf = e->sendfile_header->data; + } else { + buf = talloc_array(e->mem_ctx, uint8_t, size); + if (buf == NULL) { + return NT_STATUS_NO_MEMORY; + } } size = 0; @@ -3054,6 +3058,10 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) sconn->smb2.send_queue_len--; DLIST_REMOVE(sconn->smb2.send_queue, e); + /* + * This triggers the sendfile path via + * the destructor. + */ talloc_free(e->mem_ctx); continue; } -- 1.7.9.5 >From 2ff5fe06f6053c17ffe522a85bad298732a6500c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 12:52:21 +0100 Subject: [PATCH 05/25] s3:smb2_server: add smbd_smb2_generate_outbody() helper We can add optimization there later. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 2 ++ source3/smbd/smb2_server.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 781379c..15fc012 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -225,6 +225,8 @@ void reply_smb20ff(struct smb_request *req, uint16_t choice); void smbd_smb2_first_negprot(struct smbd_server_connection *sconn, uint8_t *inbuf, size_t size); +DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size); + NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, NTSTATUS status, DATA_BLOB *info, diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index b805c1a..7fbaf48 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -920,6 +920,11 @@ static void smb2_calculate_credits(const struct smbd_smb2_request *inreq, } } +DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size) +{ + return data_blob_talloc(req->out.vector, NULL, size); +} + static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) { struct iovec *vector; -- 1.7.9.5 >From 37545ff9b3b3c6912f937e1ef7d5c0c765f15f7c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 06/25] s3:smb2_break: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_break.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 945faa1..6446b79f 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -106,7 +106,7 @@ static void smbd_smb2_request_oplock_break_done(struct tevent_req *subreq) in_file_id_persistent = BVAL(inbody, 0x08); in_file_id_volatile = BVAL(inbody, 0x10); - outbody = data_blob_talloc(req->out.vector, NULL, 0x18); + outbody = smbd_smb2_generate_outbody(req, 0x18); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 4a7a45d2751fba05c0ac5022aa26748a8fded860 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 07/25] s3:smb2_close: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_close.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c index dce8cac..3712ffe 100644 --- a/source3/smbd/smb2_close.c +++ b/source3/smbd/smb2_close.c @@ -114,7 +114,7 @@ static void smbd_smb2_request_close_done(struct tevent_req *subreq) return; } - outbody = data_blob_talloc(req->out.vector, NULL, 0x3C); + outbody = smbd_smb2_generate_outbody(req, 0x3C); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 3782b89df6091a825dd71192af36c3e11f1f4e19 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 08/25] s3:smb2_create: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index f2fec08..52ed171 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -318,7 +318,7 @@ static void smbd_smb2_request_create_done(struct tevent_req *tsubreq) out_context_buffer_offset = SMB2_HDR_BODY + 0x58; } - outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x58); + outbody = smbd_smb2_generate_outbody(smb2req, 0x58); if (outbody.data == NULL) { error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 4570d603c1c0121d521536067ad8f54fcfa24d8c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 09/25] s3:smb2_find: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_find.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c index 46d0aa4..3f779b8 100644 --- a/source3/smbd/smb2_find.c +++ b/source3/smbd/smb2_find.c @@ -162,7 +162,7 @@ static void smbd_smb2_request_find_done(struct tevent_req *subreq) out_output_buffer_offset = SMB2_HDR_BODY + 0x08; - outbody = data_blob_talloc(req->out.vector, NULL, 0x08); + outbody = smbd_smb2_generate_outbody(req, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From c6d48bbd165f40ea32dc07173865822a931c8e12 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 10/25] s3:smb2_flush: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_flush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 00a7158..0d4c1a5 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -84,7 +84,7 @@ static void smbd_smb2_request_flush_done(struct tevent_req *subreq) return; } - outbody = data_blob_talloc(req->out.vector, NULL, 0x04); + outbody = smbd_smb2_generate_outbody(req, 0x04); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From ce411a101730d6461f5735984d2f8ed603d0980e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 11/25] s3:smb2_getinfo: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_getinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index 449aeb3..ec6181a 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -178,7 +178,7 @@ static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq) out_output_buffer_offset = SMB2_HDR_BODY + 0x08; - outbody = data_blob_talloc(req->out.vector, NULL, 0x08); + outbody = smbd_smb2_generate_outbody(req, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 33269dba04421e38a378445f2984ef1bebf7db96 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 12/25] s3:smb2_ioctl: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c index be2a798..6a19fcb 100644 --- a/source3/smbd/smb2_ioctl.c +++ b/source3/smbd/smb2_ioctl.c @@ -318,7 +318,7 @@ static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq) out_input_offset = SMB2_HDR_BODY + 0x30; out_output_offset = SMB2_HDR_BODY + 0x30; - outbody = data_blob_talloc(req->out.vector, NULL, 0x30); + outbody = smbd_smb2_generate_outbody(req, 0x30); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 63a14a55759660892000ddfe800b49197d9d20a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 13/25] s3:smb2_keepalive: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_keepalive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_keepalive.c b/source3/smbd/smb2_keepalive.c index 24a4f8e..b16ff6b 100644 --- a/source3/smbd/smb2_keepalive.c +++ b/source3/smbd/smb2_keepalive.c @@ -35,7 +35,7 @@ NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req) /* TODO: update some time stamps */ - outbody = data_blob_talloc(req->out.vector, NULL, 0x04); + outbody = smbd_smb2_generate_outbody(req, 0x04); if (outbody.data == NULL) { return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); } -- 1.7.9.5 >From 3f49d79ebb892900d9dd9c4332f7a98b2da2b30b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 14/25] s3:smb2_lock: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 671cd6f..4af3d61 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -146,7 +146,7 @@ static void smbd_smb2_request_lock_done(struct tevent_req *subreq) return; } - outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x04); + outbody = smbd_smb2_generate_outbody(smb2req, 0x04); if (outbody.data == NULL) { error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From bb972079f888b8c0623fca9542af63c775e08999 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 15/25] s3:smb2_negprot: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_negprot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index b1e71e6..6643464 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -320,7 +320,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, status); } - outbody = data_blob_talloc(req->out.vector, NULL, 0x40); + outbody = smbd_smb2_generate_outbody(req, 0x40); if (outbody.data == NULL) { return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); } -- 1.7.9.5 >From f2a3f6df9aea39917226da08193dceb9e46961ea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 16/25] s3:smb2_notify: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 228346e..7351d9f 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -130,7 +130,7 @@ static void smbd_smb2_request_notify_done(struct tevent_req *subreq) out_output_buffer_offset = SMB2_HDR_BODY + 0x08; - outbody = data_blob_talloc(req->out.vector, NULL, 0x08); + outbody = smbd_smb2_generate_outbody(req, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 13be37476f91f265b4f2450f56f89ab047e3ce9a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 17/25] s3:smb2_read: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 474eaea..05563b2 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -128,7 +128,7 @@ static void smbd_smb2_request_read_done(struct tevent_req *subreq) out_data_offset = SMB2_HDR_BODY + 0x10; - outbody = data_blob_talloc(req->out.vector, NULL, 0x10); + outbody = smbd_smb2_generate_outbody(req, 0x10); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From e2b57f958eb756cf5eea9aa629e0c8f3f04c869f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 18/25] s3:smb2_sesssetup: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_sesssetup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index edef0cc..9d7193b 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -140,7 +140,7 @@ static void smbd_smb2_request_sesssetup_done(struct tevent_req *subreq) outhdr = SMBD_SMB2_OUT_HDR_PTR(smb2req); - outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x08); + outbody = smbd_smb2_generate_outbody(smb2req, 0x08); if (outbody.data == NULL) { error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { @@ -819,7 +819,7 @@ NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req) */ talloc_steal(req, req->session); - outbody = data_blob_talloc(req->out.vector, NULL, 0x04); + outbody = smbd_smb2_generate_outbody(req, 0x04); if (outbody.data == NULL) { return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); } -- 1.7.9.5 >From b85222d1b02ac44126c727fd98664eafaa50f690 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 19/25] s3:smb2_setinfo: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_setinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index d88f7ac..97872da 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -134,7 +134,7 @@ static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq) return; } - outbody = data_blob_talloc(req->out.vector, NULL, 0x02); + outbody = smbd_smb2_generate_outbody(req, 0x02); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From 630bda64b0f0b8a5aa9a7f8c4e977960cdc35152 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 20/25] s3:smb2_tcon: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_tcon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c index c7dc928..e1f0987 100644 --- a/source3/smbd/smb2_tcon.c +++ b/source3/smbd/smb2_tcon.c @@ -135,7 +135,7 @@ static void smbd_smb2_request_tcon_done(struct tevent_req *subreq) outhdr = SMBD_SMB2_OUT_HDR_PTR(req); - outbody = data_blob_talloc(req->out.vector, NULL, 0x10); + outbody = smbd_smb2_generate_outbody(req, 0x10); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { @@ -438,7 +438,7 @@ NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req) TALLOC_FREE(req->tcon); - outbody = data_blob_talloc(req->out.vector, NULL, 0x04); + outbody = smbd_smb2_generate_outbody(req, 0x04); if (outbody.data == NULL) { return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); } -- 1.7.9.5 >From 3328161be3bf7040c67353db286062e66df962cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 14:59:07 +0100 Subject: [PATCH 21/25] s3:smb2_write: make use of smbd_smb2_generate_outbody() Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index f9cfbfc..4e138fe 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -127,7 +127,7 @@ static void smbd_smb2_request_write_done(struct tevent_req *subreq) return; } - outbody = data_blob_talloc(req->out.vector, NULL, 0x10); + outbody = smbd_smb2_generate_outbody(req, 0x10); if (outbody.data == NULL) { error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); if (!NT_STATUS_IS_OK(error)) { -- 1.7.9.5 >From d3104b09775d50b90443cc9ccc59595d3a94945f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 15:05:34 +0100 Subject: [PATCH 22/25] s3:smb2_server: optimize smbd_smb2_generate_outbody() for the common case Use a preallocated buffer for the first response in the compound chain. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 1 + source3/smbd/smb2_server.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 15fc012..f596271 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -615,6 +615,7 @@ struct smbd_smb2_request { int vector_count; #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9) uint8_t _hdr[OUTVEC_ALLOC_SIZE]; + uint8_t _body[0x58]; } out; }; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 7fbaf48..becbbed 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -922,6 +922,12 @@ static void smb2_calculate_credits(const struct smbd_smb2_request *inreq, DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size) { + if (req->current_idx <= 1) { + if (size <= sizeof(req->out._body)) { + return data_blob_const(req->out._body, size); + } + } + return data_blob_talloc(req->out.vector, NULL, size); } -- 1.7.9.5 >From 104aabcb31e83cff9d1a51e0fe9ba9b4eea58940 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 15:24:29 +0100 Subject: [PATCH 23/25] s3:smb2_server: avoid talloc_zero_array() in smbd_smb2_request_error_ex() It is only important that the content of info->data stays alive for the lifetime of the request, but the DATA_BLOB structure itself can be on the stack, while passing it as 'dyn' to smbd_smb2_request_done_ex(). Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_server.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index becbbed..cda3622 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2632,6 +2632,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, const char *location) { DATA_BLOB body; + DATA_BLOB _dyn; uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req); size_t unread_bytes = smbd_smb2_unread_bytes(req); @@ -2673,12 +2674,7 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, * *MUST BE* OUTVEC_ALLOC_SIZE. So we have room for * 1 byte without having to do an alloc. */ - info = talloc_zero_array(req->out.vector, - DATA_BLOB, - 1); - if (!info) { - return NT_STATUS_NO_MEMORY; - } + info = &_dyn; info->data = ((uint8_t *)outhdr) + OUTVEC_ALLOC_SIZE - 1; info->length = 1; -- 1.7.9.5 >From c9db11e784c0808d794ee14bab77fadd0019bc41 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 15:28:11 +0100 Subject: [PATCH 24/25] s3:smb2_server: don't assume that req->out.vector is always a valid talloc pointer We use 'req' instead as it has the same lifetime. Signed-off-by: Stefan Metzmacher --- source3/smbd/smb2_server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index cda3622..ceee35d 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -928,7 +928,7 @@ DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size) } } - return data_blob_talloc(req->out.vector, NULL, size); + return data_blob_talloc(req, NULL, size); } static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) @@ -2348,7 +2348,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req) return NT_STATUS_NO_MEMORY; } - tf = talloc_zero_array(req->out.vector, uint8_t, + tf = talloc_zero_array(req, uint8_t, SMB2_TF_HDR_SIZE); if (tf == NULL) { return NT_STATUS_NO_MEMORY; @@ -2582,7 +2582,7 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, */ uint8_t *pad; - pad = talloc_zero_array(req->out.vector, + pad = talloc_zero_array(req, uint8_t, pad_size); if (pad == NULL) { return smbd_smb2_request_error(req, @@ -2605,7 +2605,7 @@ NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req, old_dyn = SMBD_SMB2_OUT_DYN_PTR(req); new_size = old_size + pad_size; - new_dyn = talloc_zero_array(req->out.vector, + new_dyn = talloc_zero_array(req, uint8_t, new_size); if (new_dyn == NULL) { return smbd_smb2_request_error(req, -- 1.7.9.5 >From db841ef077589d83e436dcac22a07137b53f23f2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 4 Dec 2013 15:32:45 +0100 Subject: [PATCH 25/25] s3:smb2_server: avoid talloc_zero_array() in smbd_smb2_request_setup_out() In the common case with just one request, we can use a preallocated req->out.vector. Signed-off-by: Stefan Metzmacher --- source3/smbd/globals.h | 1 + source3/smbd/smb2_server.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index f596271..3baa048 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -613,6 +613,7 @@ struct smbd_smb2_request { */ struct iovec *vector; int vector_count; + struct iovec _vector[1 + SMBD_SMB2_NUM_IOV_PER_REQ]; #define OUTVEC_ALLOC_SIZE (SMB2_HDR_BODY + 9) uint8_t _hdr[OUTVEC_ALLOC_SIZE]; uint8_t _body[0x58]; diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index ceee35d..3c46efd 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -933,14 +933,21 @@ DATA_BLOB smbd_smb2_generate_outbody(struct smbd_smb2_request *req, size_t size) static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) { + TALLOC_CTX *mem_ctx; struct iovec *vector; int count; int idx; count = req->in.vector_count; - vector = talloc_zero_array(req, struct iovec, count); - if (vector == NULL) { - return NT_STATUS_NO_MEMORY; + if (count <= ARRAY_SIZE(req->out._vector)) { + mem_ctx = req; + vector = req->out._vector; + } else { + vector = talloc_zero_array(req, struct iovec, count); + if (vector == NULL) { + return NT_STATUS_NO_MEMORY; + } + mem_ctx = vector; } vector[0].iov_base = req->out.nbt_hdr; @@ -964,7 +971,7 @@ static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req) if (idx == 1) { outhdr = req->out._hdr; } else { - outhdr = talloc_zero_array(vector, uint8_t, + outhdr = talloc_zero_array(mem_ctx, uint8_t, OUTVEC_ALLOC_SIZE); if (outhdr == NULL) { return NT_STATUS_NO_MEMORY; -- 1.7.9.5