From 969d043596c0a382325d54d16dbd5e049f884fa9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 22 Sep 2015 18:01:22 -0700 Subject: [PATCH] s4: torture: Test mkdir race condition. Found by Max of LoadDynamix BUG: https://bugzilla.samba.org/show_bug.cgi?id=11486 Signed-off-by: Jeremy Allison Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Thu Sep 24 06:13:22 CEST 2015 on sn-devel-104 --- selftest/knownfail | 1 + source4/torture/smb2/create.c | 151 ++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index 447544ea07c..bf731767791 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -143,6 +143,7 @@ ^samba4.raw.acls.*.create_file ^samba4.smb2.create.*.acldir ^samba4.smb2.create.*.impersonation +^samba4.smb2.create.*.mkdir-dup # bug 11486 ^samba4.smb2.acls.*.generic ^samba4.smb2.acls.*.inheritflags ^samba4.smb2.acls.*.owner diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 44650b58dac..68dbbc1f27c 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1517,6 +1517,156 @@ done: return ret; } +/* + test SMB2 mkdir with OPEN_IF on the same name twice. + Must use 2 connections to hit the race. +*/ + +static bool test_mkdir_dup(struct torture_context *tctx, + struct smb2_tree *tree) +{ + const char *fname = "mkdir_dup"; + NTSTATUS status; + bool ret = true; + union smb_open io; + struct smb2_tree **trees; + struct smb2_request **requests; + union smb_open *ios; + int i, num_files = 2; + int num_ok = 0; + int num_created = 0; + int num_existed = 0; + + torture_comment(tctx, + "Testing SMB2 Create Directory with multiple connections\n"); + trees = talloc_array(tctx, struct smb2_tree *, num_files); + requests = talloc_array(tctx, struct smb2_request *, num_files); + ios = talloc_array(tctx, union smb_open, num_files); + if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) || + (ios == NULL)) { + torture_fail(tctx, ("talloc failed\n")); + ret = false; + goto done; + } + + tree->session->transport->options.request_timeout = 60; + + for (i=0; isession->transport->options.request_timeout = 60; + } + + /* cleanup */ + smb2_util_unlink(tree, fname); + smb2_util_rmdir(tree, fname); + + /* + base ntcreatex parms + */ + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL; + io.smb2.in.alloc_size = 0; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ| + NTCREATEX_SHARE_ACCESS_WRITE| + NTCREATEX_SHARE_ACCESS_DELETE; + io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF; + io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = fname; + io.smb2.in.create_flags = 0; + + for (i=0; istate < SMB2_REQUEST_DONE) { + unreplied = true; + break; + } + status = smb2_create_recv(requests[i], tctx, + &(ios[i].smb2)); + + if (NT_STATUS_IS_OK(status)) { + num_ok += 1; + + if (ios[i].smb2.out.create_action == + NTCREATEX_ACTION_CREATED) { + num_created++; + } + if (ios[i].smb2.out.create_action == + NTCREATEX_ACTION_EXISTED) { + num_existed++; + } + } else { + torture_fail(tctx, + talloc_asprintf(tctx, + "File %d returned status %s\n", i, + nt_errstr(status))); + } + + + requests[i] = NULL; + } + if (!unreplied) { + break; + } + + if (tevent_loop_once(tctx->ev) != 0) { + torture_fail(tctx, "tevent_loop_once failed\n"); + ret = false; + goto done; + } + } + + if (num_ok != 2) { + torture_fail(tctx, + talloc_asprintf(tctx, + "num_ok == %d\n", num_ok)); + ret = false; + } + if (num_created != 1) { + torture_fail(tctx, + talloc_asprintf(tctx, + "num_created == %d\n", num_created)); + ret = false; + } + if (num_existed != 1) { + torture_fail(tctx, + talloc_asprintf(tctx, + "num_existed == %d\n", num_existed)); + ret = false; + } +done: + smb2_deltree(tree, fname); + + return ret; +} + + /* basic testing of SMB2 read */ @@ -1535,6 +1685,7 @@ struct torture_suite *torture_smb2_create_init(void) torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file); torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir); torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl); + torture_suite_add_1smb2_test(suite, "mkdir-dup", test_mkdir_dup); suite->description = talloc_strdup(suite, "SMB2-CREATE tests");