diff options
author | Volker Lendecke <vl@samba.org> | 2018-01-11 11:55:39 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2018-01-14 14:47:15 +0100 |
commit | 0abe16a5343de9a69bb5cccbad9809b28b642f45 (patch) | |
tree | 61c2a7fe899f8f4c53e7538bdfd85a9dd29ac5b3 /source4/torture/smb2 | |
parent | cd288a08500b1cc38ef26e5cb8ef754b4da658b6 (diff) | |
download | samba-0abe16a5343de9a69bb5cccbad9809b28b642f45.tar.gz |
torture: Add test for channel sequence number handling
We run into an assert when the csn wraps
Bug: https://bugzilla.samba.org/show_bug.cgi?id=13215
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
Autobuild-Date(master): Sun Jan 14 14:47:15 CET 2018 on sn-devel-144
Diffstat (limited to 'source4/torture/smb2')
-rw-r--r-- | source4/torture/smb2/replay.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/source4/torture/smb2/replay.c b/source4/torture/smb2/replay.c index 889ecd73c72..2ef40445aee 100644 --- a/source4/torture/smb2/replay.c +++ b/source4/torture/smb2/replay.c @@ -2425,6 +2425,102 @@ done: return ret; } +static bool test_replay7(struct torture_context *tctx, struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + struct smb2_transport *transport = tree->session->transport; + NTSTATUS status; + struct smb2_handle _dh; + struct smb2_handle *dh = NULL; + struct smb2_notify notify; + struct smb2_request *req; + union smb_fileinfo qfinfo; + bool ret = false; + + if (smbXcli_conn_protocol(transport->conn) < PROTOCOL_SMB3_00) { + torture_skip(tctx, "SMB 3.X Dialect family required for " + "replay tests\n"); + } + + torture_comment(tctx, "Notify across increment/decrement of csn\n"); + + smbXcli_conn_set_force_channel_sequence(transport->conn, true); + + status = torture_smb2_testdir(tree, BASEDIR, &_dh); + CHECK_STATUS(status, NT_STATUS_OK); + dh = &_dh; + + notify.in.recursive = 0x0000; + notify.in.buffer_size = 0xffff; + notify.in.file.handle = _dh; + notify.in.completion_filter = FILE_NOTIFY_CHANGE_FILE_NAME; + notify.in.unknown = 0x00000000; + + /* + * This posts a long-running request with csn==0 to "dh". Now + * op->request_count==1 in smb2_server.c. + */ + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0); + req = smb2_notify_send(tree, ¬ify); + + qfinfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_POSITION_INFORMATION, + .generic.in.file.handle = _dh + }; + + /* + * This sequence of 2 dummy requests moves + * op->request_count==1 to op->pre_request_count. The numbers + * used avoid int16 overflow. + */ + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 30000); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 60000); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * This final request turns the op->global->channel_sequence + * to the same as we had when sending the notify above. The + * notify's request count has in the meantime moved to + * op->pre_request_count. + */ + + smb2cli_session_reset_channel_sequence(tree->session->smbXcli, 0); + status = smb2_getinfo_file(tree, mem_ctx, &qfinfo); + CHECK_STATUS(status, NT_STATUS_OK); + + /* + * At this point op->request_count==0. + * + * The next cancel makes us reply to the notify. Because the + * csn we currently use is the same as we used when sending + * the notify, smbd thinks it must decrement op->request_count + * and not op->pre_request_count. + */ + + status = smb2_cancel(req); + CHECK_STATUS(status, NT_STATUS_OK); + + status = smb2_notify_recv(req, mem_ctx, ¬ify); + CHECK_STATUS(status, NT_STATUS_CANCELLED); + + ret = true; + +done: + if (dh != NULL) { + smb2_util_close(tree, _dh); + } + smb2_deltree(tree, BASEDIR); + talloc_free(tree); + talloc_free(mem_ctx); + + return ret; +} + struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -2445,6 +2541,7 @@ struct torture_suite *torture_smb2_replay_init(TALLOC_CTX *ctx) torture_suite_add_1smb2_test(suite, "replay4", test_replay4); torture_suite_add_1smb2_test(suite, "replay5", test_replay5); torture_suite_add_1smb2_test(suite, "replay6", test_replay6); + torture_suite_add_1smb2_test(suite, "replay7", test_replay7); suite->description = talloc_strdup(suite, "SMB2 REPLAY tests"); |