]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: smbtorture3: Add test for setting delete on close on a directory, then creating...
authorJeremy Allison <jra@samba.org>
Wed, 3 Nov 2021 23:50:10 +0000 (16:50 -0700)
committerRalph Boehme <slow@samba.org>
Thu, 4 Nov 2021 08:22:34 +0000 (08:22 +0000)
Exposes an existing problem where "ret" is overwritten
in the directory scan.

Add knownfail.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14892

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/del_on_close_nonempty [new file with mode: 0644]
source3/selftest/tests.py
source3/torture/proto.h
source3/torture/test_smb2.c
source3/torture/torture.c

diff --git a/selftest/knownfail.d/del_on_close_nonempty b/selftest/knownfail.d/del_on_close_nonempty
new file mode 100644 (file)
index 0000000..7109b99
--- /dev/null
@@ -0,0 +1 @@
+^samba3.smbtorture_s3.plain.SMB2-DEL-ON-CLOSE-NONEMPTY.smbtorture\(fileserver\)
index 5aba11c11b130d106d87088fd5c64d393bf5a03c..41ed728a03e738472884ec4417b23d7499f64663 100755 (executable)
@@ -256,6 +256,21 @@ plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-LIST-DIR-ASYNC",
                 smbtorture3,
                 "",
                 "-l $LOCAL_PATH"])
+#
+# SMB2-DEL-ON-CLOSE-NONEMPTY needs to run against a special fileserver share veto_files_delete
+#
+plantestsuite("samba3.smbtorture_s3.plain.%s" % "SMB2-DEL-ON-CLOSE-NONEMPTY",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-DEL-ON-CLOSE-NONEMPTY',
+                '//$SERVER_IP/veto_files_delete',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "",
+                "-l $LOCAL_PATH"])
+
 
 
 shares = [
index 4db267c92b0723ac7fced22df924fe19f2847229..65fa17523d80219a3f832951edc02f5d3ba617da 100644 (file)
@@ -120,6 +120,7 @@ bool run_smb2_sacl(int dummy);
 bool run_smb2_quota1(int dummy);
 bool run_smb2_stream_acl(int dummy);
 bool run_list_dir_async_test(int dummy);
+bool run_delete_on_close_non_empty(int dummy);
 bool run_chain3(int dummy);
 bool run_local_conv_auth_info(int dummy);
 bool run_local_sprintf_append(int dummy);
index b186ea4edac87cd6db9b947f11d751823414e518..0fac5125c081ffccc0666dd17af22632cfb76352 100644 (file)
@@ -3228,3 +3228,139 @@ bool run_list_dir_async_test(int dummy)
        (void)cli_rmdir(cli, dname);
        return ret;
 }
+
+/*
+ * Test delete a directory fails if a file is created
+ * in a directory after the delete on close is set.
+ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=14892
+ */
+
+bool run_delete_on_close_non_empty(int dummy)
+{
+       struct cli_state *cli = NULL;
+       NTSTATUS status;
+       const char *dname = "DEL_ON_CLOSE_DIR";
+       const char *fname = "DEL_ON_CLOSE_DIR\\testfile";
+       uint16_t fnum = (uint16_t)-1;
+       uint16_t fnum1 = (uint16_t)-1;
+       bool ret = false;
+
+       printf("SMB2 delete on close nonempty\n");
+
+       if (!torture_init_connection(&cli)) {
+               return false;
+       }
+
+       status = smbXcli_negprot(cli->conn,
+                               cli->timeout,
+                               PROTOCOL_SMB2_02,
+                               PROTOCOL_SMB3_11);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("smbXcli_negprot returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_session_setup_creds(cli, torture_creds);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_session_setup returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       status = cli_tree_connect(cli, share, "?????", NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_tree_connect returned %s\n", nt_errstr(status));
+               return false;
+       }
+
+       /* Ensure directory doesn't exist. */
+       (void)cli_unlink(cli,
+                        fname,
+                        FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       (void)cli_rmdir(cli, dname);
+
+       /* Create target directory. */
+       status = cli_ntcreate(cli,
+                               dname,
+                               0,
+                               DELETE_ACCESS|FILE_READ_DATA,
+                               FILE_ATTRIBUTE_DIRECTORY,
+                               FILE_SHARE_READ|
+                                       FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_CREATE,
+                               FILE_DIRECTORY_FILE,
+                               0,
+                               &fnum,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate for directory %s returned %s\n",
+                               dname,
+                               nt_errstr(status));
+               goto out;
+       }
+
+       /* Now set the delete on close bit. */
+       status = cli_nt_delete_on_close(cli, fnum, 1);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_cli_nt_delete_on_close set for directory "
+                       "%s returned %s\n",
+                       dname,
+                       nt_errstr(status));
+               goto out;
+       }
+
+       /* Create file inside target directory. */
+       /*
+        * NB. On Windows this will return NT_STATUS_DELETE_PENDING.  Only on
+        * Samba will this succeed by default (the option "check parent
+        * directory delete on close" configures behaviour), but we're using
+        * this to test a race condition.
+        */
+       status = cli_ntcreate(cli,
+                               fname,
+                               0,
+                               FILE_READ_DATA,
+                               FILE_ATTRIBUTE_NORMAL,
+                               FILE_SHARE_READ|
+                                       FILE_SHARE_WRITE|
+                                       FILE_SHARE_DELETE,
+                               FILE_CREATE,
+                               0,
+                               0,
+                               &fnum1,
+                               NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("cli_ntcreate for file %s returned %s\n",
+                               fname,
+                               nt_errstr(status));
+               goto out;
+       }
+       cli_close(cli, fnum1);
+       fnum1 = (uint16_t)-1;
+
+       /* Now the close should fail. */
+       status = cli_close(cli, fnum);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
+               printf("cli_close for directory %s returned %s\n",
+                               dname,
+                               nt_errstr(status));
+               goto out;
+       }
+
+       ret = true;
+
+  out:
+
+       if (fnum1 != (uint16_t)-1) {
+               cli_close(cli, fnum1);
+       }
+       if (fnum != (uint16_t)-1) {
+               cli_nt_delete_on_close(cli, fnum, 0);
+               cli_close(cli, fnum);
+       }
+       (void)cli_unlink(cli,
+                        fname,
+                        FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+       (void)cli_rmdir(cli, dname);
+       return ret;
+}
index 79a9c65073c902b72b35a77b527a9940b32e15cb..197e1990e16f69528d76ca62876dfc700577e794 100644 (file)
@@ -15249,6 +15249,10 @@ static struct {
                .name  = "SMB2-LIST-DIR-ASYNC",
                .fn    = run_list_dir_async_test,
        },
+       {
+               .name  = "SMB2-DEL-ON-CLOSE-NONEMPTY",
+               .fn    = run_delete_on_close_non_empty,
+       },
        {
                .name  = "CLEANUP1",
                .fn    = run_cleanup1,