summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2018-01-11 15:34:45 +0100
committerStefan Metzmacher <metze@samba.org>2018-01-14 10:26:05 +0100
commit0b57434151a8334a6e9b9b7542824ce4915421a2 (patch)
tree8a148e7184186689efcfa1dbc359d5e779ab7231
parent03f65a7cdc91091a171269cfebc9916f2f678388 (diff)
downloadsamba-0b57434151a8334a6e9b9b7542824ce4915421a2.tar.gz
smbd: Fix channel sequence number checks for long-running requests
When the client's supplied csn overflows and hits a pending, long-running request's csn, we panic. Fix this by counting the overflows in smbXsrv_open_global0->channel_generation Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Volker Lendecke <vl@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--source3/librpc/idl/smbXsrv.idl3
-rw-r--r--source3/smbd/globals.h1
-rw-r--r--source3/smbd/smb2_server.c15
3 files changed, 17 insertions, 2 deletions
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index 1bfa51ea912..d3f8d30d1e3 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -430,7 +430,8 @@ interface smbXsrv
uint32 durable_timeout_msec;
boolean8 durable;
DATA_BLOB backend_cookie;
- hyper channel_sequence;
+ uint16 channel_sequence;
+ hyper channel_generation;
} smbXsrv_open_global0;
typedef union {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 78f1260909d..69db07a490b 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -744,6 +744,7 @@ struct smbd_smb2_request {
* adapted again in reply.
*/
bool request_counters_updated;
+ uint64_t channel_generation;
/*
* The sub request for async backend calls.
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 69788e9b2f5..a731880e98e 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2158,6 +2158,7 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts(
struct smbXsrv_connection *xconn = req->xconn;
const uint8_t *inhdr;
uint16_t channel_sequence;
+ uint8_t generation_wrap = 0;
uint32_t flags;
int cmp;
struct smbXsrv_open *op;
@@ -2184,6 +2185,14 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts(
channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
cmp = channel_sequence - op->global->channel_sequence;
+ if (cmp < 0) {
+ /*
+ * csn wrap. We need to watch out for long-running
+ * requests that are still sitting on a previously
+ * used csn. SMB2_OP_NOTIFY can take VERY long.
+ */
+ generation_wrap += 1;
+ }
if (abs(cmp) > INT16_MAX) {
/*
@@ -2239,6 +2248,7 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts(
op->pre_request_count += op->request_count;
op->request_count = 1;
op->global->channel_sequence = channel_sequence;
+ op->global->channel_generation += generation_wrap;
update_open = true;
req->request_counters_updated = true;
} else if (modify_call) {
@@ -2252,12 +2262,14 @@ static NTSTATUS smbd_smb2_request_dispatch_update_counts(
op->pre_request_count += op->request_count;
op->request_count = 1;
op->global->channel_sequence = channel_sequence;
+ op->global->channel_generation += generation_wrap;
update_open = true;
req->request_counters_updated = true;
} else if (modify_call) {
return NT_STATUS_FILE_NOT_AVAILABLE;
}
}
+ req->channel_generation = op->global->channel_generation;
if (update_open) {
status = smbXsrv_open_update(op);
@@ -2744,7 +2756,8 @@ static void smbd_smb2_request_reply_update_counts(struct smbd_smb2_request *req)
inhdr = SMBD_SMB2_IN_HDR_PTR(req);
channel_sequence = SVAL(inhdr, SMB2_HDR_CHANNEL_SEQUENCE);
- if (op->global->channel_sequence == channel_sequence) {
+ if ((op->global->channel_sequence == channel_sequence) &&
+ (op->global->channel_generation == req->channel_generation)) {
SMB_ASSERT(op->request_count > 0);
op->request_count -= 1;
} else {