summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 {