From dc0f69fd13c61cb3b7162a2e92050fad653d05cf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 26 Aug 2024 14:42:02 +0200 Subject: [PATCH] s4:torture/smb2: add smb2.durable-v2-regressions.durable_v2_reconnect_bug15624 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15624 Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner (cherry picked from commit ef4ef04e7f83b1029446ff8b5fc5fdf4ab33edbd) --- selftest/skip | 1 + source4/torture/smb2/durable_v2_open.c | 118 +++++++++++++++++++++++++ source4/torture/smb2/smb2.c | 2 + 3 files changed, 121 insertions(+) diff --git a/selftest/skip b/selftest/skip index cc2fe8979e8..f97acafe44e 100644 --- a/selftest/skip +++ b/selftest/skip @@ -148,3 +148,4 @@ bench # don't run benchmarks in our selftest ^samba4.smb2.mkdir.*\(ad_dc_ntvfs\)$ # Ignore ad_dc_ntvfs since this is a new test ^samba.tests.reparsepoints.* ^samba3.blackbox.open-eintr.* +smb2.durable-v2-regressions # Only used in blackbox tests diff --git a/source4/torture/smb2/durable_v2_open.c b/source4/torture/smb2/durable_v2_open.c index 9b9af11124c..7447dd287a4 100644 --- a/source4/torture/smb2/durable_v2_open.c +++ b/source4/torture/smb2/durable_v2_open.c @@ -2355,6 +2355,112 @@ done: return ret; } +/** + * basic test for doing a durable open + * tcp disconnect, reconnect, do a durable reopen (succeeds) + */ +static bool test_durable_v2_reconnect_bug15624(struct torture_context *tctx, + struct smb2_tree *tree, + struct smb2_tree *tree2) +{ + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc_new(tctx); + char fname[256]; + struct smb2_handle _h; + struct smb2_handle *h = NULL; + struct smb2_create io; + struct GUID create_guid = GUID_random(); + struct smbcli_options options; + uint64_t previous_session_id; + uint8_t b = 0; + bool ret = true; + bool ok; + + if (!torture_setting_bool(tctx, "bug15624", false)) { + torture_comment(tctx, + "share requires:\n" + "'vfs objects = error_inject'\n" + "'error_inject:durable_reconnect=st_ex_nlink'\n" + "test requires:\n" + "'--option=torture:bug15624=yes'\n"); + torture_skip(tctx, "'--option=torture:bug15624=yes' missing"); + } + + options = tree->session->transport->options; + previous_session_id = smb2cli_session_current_id(tree->session->smbXcli); + + /* Choose a random name in case the state is left a little funky. */ + snprintf(fname, + sizeof(fname), + "durable_v2_reconnect_bug15624_%s.dat", + generate_random_str(tctx, 8)); + + smb2_util_unlink(tree, fname); + + smb2_oplock_create_share(&io, fname, + smb2_util_share_access(""), + smb2_util_oplock_level("b")); + io.in.durable_open = false; + io.in.durable_open_v2 = true; + io.in.persistent_open = false; + io.in.create_guid = create_guid; + io.in.timeout = 0; + + status = smb2_create(tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OK); + + _h = io.out.file.handle; + h = &_h; + CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b")); + CHECK_VAL(io.out.durable_open_v2, true); + + status = smb2_util_write(tree, *h, &b, 0, 1); + CHECK_STATUS(status, NT_STATUS_OK); + + /* disconnect, leaving the durable open */ + TALLOC_FREE(tree); + h = NULL; + + ok = torture_smb2_connection_ext(tctx, previous_session_id, + &options, &tree); + torture_assert_goto(tctx, ok, ret, done, "couldn't reconnect, bailing\n"); + + ZERO_STRUCT(io); + io.in.fname = fname; + io.in.durable_open_v2 = false; + io.in.durable_handle_v2 = &_h; + io.in.create_guid = create_guid; + + /* + * This assumes 'error_inject:durable_reconnect = st_ex_nlink' + * will cause the durable reconnect to fail... + * in order to have a regression test for the dead lock. + */ + status = smb2_create(tree, mem_ctx, &io); + CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); + + /* + * With the regression this will fail with + * a timeout... + */ + status = smb2_util_unlink(tree2, fname); + CHECK_STATUS(status, NT_STATUS_OK); + +done: + if (h != NULL) { + smb2_util_close(tree, *h); + } + TALLOC_FREE(tree); + + smb2_util_unlink(tree2, fname); + + TALLOC_FREE(tree2); + + talloc_free(mem_ctx); + + return ret; +} + struct torture_suite *torture_smb2_durable_v2_delay_init(TALLOC_CTX *ctx) { struct torture_suite *suite = @@ -2369,3 +2475,15 @@ struct torture_suite *torture_smb2_durable_v2_delay_init(TALLOC_CTX *ctx) return suite; } + +struct torture_suite *torture_smb2_durable_v2_regressions_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = + torture_suite_create(ctx, "durable-v2-regressions"); + + torture_suite_add_2smb2_test(suite, + "durable_v2_reconnect_bug15624", + test_durable_v2_reconnect_bug15624); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index 28a62f49c47..9e411e1a5f9 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -170,6 +170,8 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_smb2_durable_v2_open_init(suite)); torture_suite_add_suite(suite, torture_smb2_durable_v2_delay_init(suite)); + torture_suite_add_suite(suite, + torture_smb2_durable_v2_regressions_init(suite)); torture_suite_add_suite(suite, torture_smb2_dir_init(suite)); torture_suite_add_suite(suite, torture_smb2_lease_init(suite)); torture_suite_add_suite(suite, torture_smb2_compound_init(suite));