1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-21 18:04:06 +03:00

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>
(cherry picked from commit 0b57434151a8334a6e9b9b7542824ce4915421a2)
This commit is contained in:
Volker Lendecke 2018-01-11 15:34:45 +01:00 committed by Stefan Metzmacher
parent c3bce29f1e
commit 082c08efb4
3 changed files with 17 additions and 2 deletions

View File

@ -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 {

View File

@ -733,6 +733,7 @@ struct smbd_smb2_request {
* adapted again in reply.
*/
bool request_counters_updated;
uint64_t channel_generation;
/*
* The sub request for async backend calls.

View File

@ -2141,6 +2141,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;
@ -2167,6 +2168,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) {
/*
@ -2222,6 +2231,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) {
@ -2235,12 +2245,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);
@ -2726,7 +2738,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 {