From 722d9650f8461ccb39d4e7b404ffbfed7ed86670 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:49:24 +0200 Subject: [PATCH 1/9] s4:torture: add a file-id related test Note I'm using the share vfs_fruit_xattr because I need a share with both a streams and a acl_* VFS object. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 2ecab3c60abf9baa16a6a5e3eba0fc4720def840) --- selftest/knownfail.d/samba3.smb2.create | 1 + source3/selftest/tests.py | 2 + source4/selftest/tests.py | 1 + source4/torture/smb2/create.c | 212 ++++++++++++++++++++++++ source4/torture/smb2/smb2.c | 1 + 5 files changed, 217 insertions(+) create mode 100644 selftest/knownfail.d/samba3.smb2.create diff --git a/selftest/knownfail.d/samba3.smb2.create b/selftest/knownfail.d/samba3.smb2.create new file mode 100644 index 000000000000..89455dacdf0c --- /dev/null +++ b/selftest/knownfail.d/samba3.smb2.create @@ -0,0 +1 @@ +^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 31cb8ca33f19..20f2eea76611 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -689,6 +689,8 @@ for t in tests: plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/delete_readonly -U$USERNAME%$PASSWORD --option=torture:delete_readonly=true') plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') + elif t == "smb2.fileid": + plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/vfs_fruit_xattr -U$USERNAME%$PASSWORD') elif t == "rpc.wkssvc": plansmbtorture4testsuite(t, "ad_member", '//$SERVER/tmp -U$DC_USERNAME%$DC_PASSWORD') elif t == "rpc.srvsvc": diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index bf3dd98cbef3..3f55649f2177 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -342,6 +342,7 @@ smb2_s3only = [ "smb2.kernel-oplocks", "smb2.durable-v2-delay", "smb2.aio_delay", + "smb2.fileid", ] smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only] diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 9b32062ab07f..beddefc4c8db 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -1905,6 +1905,204 @@ done: return ret; } +static bool test_fileid(struct torture_context *tctx, + struct smb2_tree *tree) +{ + TALLOC_CTX *mem_ctx = talloc_new(tctx); + const char *fname = DNAME "\\foo"; + const char *sname = DNAME "\\foo:bar"; + struct smb2_handle testdirh; + struct smb2_handle h1; + struct smb2_create create; + union smb_fileinfo finfo; + union smb_setfileinfo sinfo; + struct smb2_find f; + unsigned int count; + union smb_search_data *d; + uint64_t fileid; + uint64_t stream_fileid; + NTSTATUS status; + bool ret = true; + + smb2_deltree(tree, DNAME); + + status = torture_smb2_testdir(tree, DNAME, &testdirh); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir failed\n"); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN_IF, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + fileid = BVAL(&create.out.on_disk_id, 0); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF, + .in.fname = sname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + stream_fileid = BVAL(&create.out.on_disk_id, 0); + torture_assert_u64_equal_goto(tctx, stream_fileid, fileid, + ret, done, "bad fileid\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + status = smb2_util_write(tree, h1, "foo", 0, strlen("foo")); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_util_write failed\n"); + + sinfo = (union smb_setfileinfo) { + .basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION, + .basic_info.in.file.handle = h1, + }; + unix_to_nt_time(&sinfo.basic_info.in.write_time, time(NULL)); + + status = smb2_setinfo_file(tree, &sinfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_setinfo_file failed\n"); + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_getinfo_file failed\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + + create = (struct smb2_create) { + .in.desired_access = SEC_FILE_ALL, + .in.share_access = NTCREATEX_SHARE_ACCESS_MASK, + .in.file_attributes = FILE_ATTRIBUTE_NORMAL, + .in.create_disposition = NTCREATEX_DISP_OPEN, + .in.fname = fname, + .in.query_on_disk_id = true, + }; + + status = smb2_create(tree, tctx, &create); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "test file could not be created\n"); + h1 = create.out.file.handle; + + finfo = (union smb_fileinfo) { + .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION, + .generic.in.file.handle = h1, + }; + + status = smb2_getinfo_file(tree, tctx, &finfo); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "torture_smb2_testdir\n"); + + torture_assert_u64_equal_goto(tctx, finfo.all_info2.out.file_id, fileid, + ret, done, "bad fileid\n"); + + f = (struct smb2_find) { + .in.file.handle = testdirh, + .in.pattern = "foo", + .in.max_response_size = 0x1000, + .in.level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO, + .in.continue_flags = SMB2_CONTINUE_FLAG_RESTART, + }; + + status = smb2_find_level(tree, tree, &f, &count, &d); + torture_assert_ntstatus_ok_goto(tctx, status, ret, done, + "smb2_find_level failed\n"); + + torture_assert_u64_equal_goto(tctx, + d->id_both_directory_info.file_id, + fileid, + ret, done, "bad fileid\n"); + + smb2_util_close(tree, h1); + +done: + smb2_util_close(tree, testdirh); + smb2_deltree(tree, DNAME); + talloc_free(mem_ctx); + return ret; +} + /* basic testing of SMB2 read */ @@ -1942,3 +2140,17 @@ struct torture_suite *torture_smb2_twrp_init(TALLOC_CTX *ctx) return suite; } + +/* + basic testing of SMB2 File-IDs +*/ +struct torture_suite *torture_smb2_fileid_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = torture_suite_create(ctx, "fileid"); + + torture_suite_add_1smb2_test(suite, "fileid", test_fileid); + + suite->description = talloc_strdup(suite, "SMB2-CREATE tests"); + + return suite; +} diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c index e57dba3c1d94..7cca19e65d32 100644 --- a/source4/torture/smb2/smb2.c +++ b/source4/torture/smb2/smb2.c @@ -155,6 +155,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx) torture_suite_add_suite(suite, torture_smb2_aio_delay_init(suite)); torture_suite_add_suite(suite, torture_smb2_create_init(suite)); torture_suite_add_suite(suite, torture_smb2_twrp_init(suite)); + torture_suite_add_suite(suite, torture_smb2_fileid_init(suite)); torture_suite_add_suite(suite, torture_smb2_acls_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_init(suite)); torture_suite_add_suite(suite, torture_smb2_notify_inotify_init(suite)); -- 2.17.1 From 80d08a76b43a336644130ca92c16d4f5cbda642a Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Tue, 3 Sep 2019 17:50:54 +0200 Subject: [PATCH 2/9] lib: add round_timespec_to_nttime() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 5403bb22e6cb39baf6dc1b91558744d41e9f6f64) --- lib/util/time.c | 9 +++++++++ lib/util/time.h | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/util/time.c b/lib/util/time.c index bd067f84e8e5..3a6043025f41 100644 --- a/lib/util/time.c +++ b/lib/util/time.c @@ -956,6 +956,15 @@ void round_timespec_to_usec(struct timespec *ts) } } +/**************************************************************************** + Round a timespec to NTTIME resolution. +****************************************************************************/ + +void round_timespec_to_nttime(struct timespec *ts) +{ + ts->tv_nsec = (ts->tv_nsec / 100) * 100; +} + /**************************************************************************** Put a 8 byte filetime from a struct timespec. Uses GMT. ****************************************************************************/ diff --git a/lib/util/time.h b/lib/util/time.h index 1988b330576e..7a8f8af35d98 100644 --- a/lib/util/time.h +++ b/lib/util/time.h @@ -328,6 +328,7 @@ struct timespec timespec_min(const struct timespec *ts1, int timespec_compare(const struct timespec *ts1, const struct timespec *ts2); void round_timespec_to_sec(struct timespec *ts); void round_timespec_to_usec(struct timespec *ts); +void round_timespec_to_nttime(struct timespec *ts); NTTIME unix_timespec_to_nt_time(struct timespec ts); #endif /* _SAMBA_TIME_H_ */ -- 2.17.1 From fd8ae4525fc2fe36cfe7cb03528e8651ecb2e14f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 11:12:08 +0200 Subject: [PATCH 3/9] s3:lib: round itime to NTTIME resolution in make_file_id_from_itime() The rounding is needed because when a file is created via eg an SMB2 CREATE request, we need to calculate the correct File-ID for the QFID Create-Context or for a subsequent GETINFO SMB request on the same file-handle. Any later metadata request that received the File-ID will do so by going through dos_mode() -> ... -> parse_dos_attribute_blob(), where the File-ID will be calculated from the on-disk itime which has NTTIME resolution. As long as that is the only available itime backend, I'm rounding itime inside make_file_id_from_itime(), not in the callers. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 84abeaa60ffced276da2b28b8add6efaa6da5ca6) --- source3/lib/file_id.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/lib/file_id.c b/source3/lib/file_id.c index 7d4fb006afec..21f22ffbf3be 100644 --- a/source3/lib/file_id.c +++ b/source3/lib/file_id.c @@ -102,6 +102,8 @@ uint64_t make_file_id_from_itime(SMB_STRUCT_STAT *st) return ino; } + round_timespec_to_nttime(&itime); + file_id_low = itime.tv_nsec; if (file_id_low == 0) { /* -- 2.17.1 From dc33c523d5c51ff9595a0b7cf9afeb34313ca4fd Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:48:40 +0200 Subject: [PATCH 4/9] s3:smbd: ensure to update the File-ID in struct smb_filename Initialize the File-ID in fsp->fsp_name->st, any subsequent metadata fetch on this file-handle needs this, eg QFID SMB2 Create-Context or GETINFO SMB requests. It would be nice if SMB_VFS_SET_DOS_ATTRIBUTE() would do this, unfortunately it gets a const struct smb_filename. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 3483b75fed8985bd2968bbf8c85985107115fba8) --- source3/smbd/open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2ee4a2c4fcae..a5650ac9c2dd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3710,6 +3710,15 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (info == FILE_WAS_CREATED) { smb_fname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; + + if (lp_store_dos_attributes(SNUM(conn)) && + smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) + { + uint64_t file_id; + + file_id = make_file_id_from_itime(&smb_fname->st); + update_stat_ex_file_id(&smb_fname->st, file_id); + } } if (info != FILE_WAS_OPENED) { @@ -3862,6 +3871,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, smb_dname->st.st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME; if (lp_store_dos_attributes(SNUM(conn))) { + if (smb_dname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID) + { + uint64_t file_id; + + file_id = make_file_id_from_itime(&smb_dname->st); + update_stat_ex_file_id(&smb_dname->st, file_id); + } + if (!posix_open) { file_set_dosmode(conn, smb_dname, file_attributes | FILE_ATTRIBUTE_DIRECTORY, -- 2.17.1 From 25840ad36c9c59368920fb4bb6f85f2c6fe079f3 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:48:57 +0200 Subject: [PATCH 5/9] vfs_catia: stat info may have been updated, make sure to return changes BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit 4e49999c97f53acc7006f1dc6b6812bb0e156db5) --- source3/modules/vfs_catia.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 762491ede314..1869d21dbcff 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -2377,6 +2377,10 @@ static NTSTATUS catia_get_dos_attributes(struct vfs_handle_struct *handle, status = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, mapped_smb_fname, dosmode); + if (NT_STATUS_IS_OK(status)) { + smb_fname->st = mapped_smb_fname->st; + } + TALLOC_FREE(mapped_name); TALLOC_FREE(mapped_smb_fname); -- 2.17.1 From 69aca687df988001bdd75fded6a002c6389a225c Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Fri, 30 Aug 2019 14:49:47 +0200 Subject: [PATCH 6/9] s3:lib: add update_stat_ex_from_saved_stat() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit ac18730f10ce96a607a3a07e1360b522ebf72f38) --- source3/include/proto.h | 2 ++ source3/lib/system.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/source3/include/proto.h b/source3/include/proto.h index 8b387f7c5632..ad6f3bbf9c34 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -223,6 +223,8 @@ void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts); void update_stat_ex_itime(struct stat_ex *dst, struct timespec itime); void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time); void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id); +void update_stat_ex_from_saved_stat(struct stat_ex *dst, + const struct stat_ex *src); int sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf, bool fake_dir_create_times); int sys_fstat(int fd, SMB_STRUCT_STAT *sbuf, diff --git a/source3/lib/system.c b/source3/lib/system.c index a67388e436a8..0620439c944a 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -355,6 +355,26 @@ void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id) dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID; } +void update_stat_ex_from_saved_stat(struct stat_ex *dst, + const struct stat_ex *src) +{ + if (!VALID_STAT(*src)) { + return; + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) { + update_stat_ex_create_time(dst, src->st_ex_btime); + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) { + update_stat_ex_itime(dst, src->st_ex_itime); + } + + if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) { + update_stat_ex_file_id(dst, src->st_ex_file_id); + } +} + void init_stat_ex_from_stat (struct stat_ex *dst, const struct stat *src, bool fake_dir_create_times) -- 2.17.1 From cf324a823c55932695eae438a6d5b37a5f556b32 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 07:57:34 +0200 Subject: [PATCH 7/9] s3: replace fsp_stat() with vfs_stat_fsp() Both functions do the same, they differ just in the type of the returned result. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit ab03394969f8a4c748aea7d0d8ed37f9ced6cc30) --- source3/modules/vfs_dirsort.c | 13 ++++++++----- source3/smbd/fileio.c | 17 ----------------- source3/smbd/proto.h | 1 - source3/smbd/reply.c | 23 +++++++++++++++-------- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index c23f6f0152d4..c6b5ea41c936 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -44,19 +44,22 @@ static bool get_sorted_dir_mtime(vfs_handle_struct *handle, { int ret; struct timespec mtime; + NTSTATUS status; if (data->fsp) { - ret = fsp_stat(data->fsp); + status = vfs_stat_fsp(data->fsp); + if (!NT_STATUS_IS_OK(status)) { + return false; + } mtime = data->fsp->fsp_name->st.st_ex_mtime; } else { ret = SMB_VFS_STAT(handle->conn, data->smb_fname); + if (ret == -1) { + return false; + } mtime = data->smb_fname->st.st_ex_mtime; } - if (ret == -1) { - return false; - } - *ret_mtime = mtime; return true; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index a00b368f92bc..067ce5a9ad40 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -1068,20 +1068,3 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug } return NT_STATUS_OK; } - -/************************************************************ - Perform a stat whether a valid fd or not. -************************************************************/ - -int fsp_stat(files_struct *fsp) -{ - if (fsp->fh->fd == -1) { - if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { - return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); - } else { - return SMB_VFS_STAT(fsp->conn, fsp->fsp_name); - } - } else { - return SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); - } -} diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index cd1ec9a1f9e8..10ffaf6e4809 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -342,7 +342,6 @@ void delete_write_cache(files_struct *fsp); void set_filelen_write_cache(files_struct *fsp, off_t file_size); ssize_t flush_write_cache(files_struct *fsp, enum flush_reason_enum reason); NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_through); -int fsp_stat(files_struct *fsp); /* The following definitions come from smbd/filename.c */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index dec67a10caeb..35d1ae772d52 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3662,6 +3662,7 @@ void reply_readbraw(struct smb_request *req) files_struct *fsp; struct lock_struct lock; off_t size = 0; + NTSTATUS status; START_PROFILE(SMBreadbraw); @@ -3759,7 +3760,8 @@ void reply_readbraw(struct smb_request *req) return; } - if (fsp_stat(fsp) == 0) { + status = vfs_stat_fsp(fsp); + if (NT_STATUS_IS_OK(status)) { size = fsp->fsp_name->st.st_ex_size; } @@ -4090,6 +4092,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, ssize_t nread = -1; struct lock_struct lock; int saved_errno = 0; + NTSTATUS status; init_strict_lock_struct(fsp, (uint64_t)req->smbpid, (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK, @@ -4114,8 +4117,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */]; DATA_BLOB header; - if(fsp_stat(fsp) == -1) { - reply_nterror(req, map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); goto out; } @@ -5323,6 +5327,7 @@ void reply_lseek(struct smb_request *req) off_t res= -1; int mode,umode; files_struct *fsp; + NTSTATUS status; START_PROFILE(SMBlseek); @@ -5367,9 +5372,9 @@ void reply_lseek(struct smb_request *req) if(errno == EINVAL) { off_t current_pos = startpos; - if(fsp_stat(fsp) == -1) { - reply_nterror(req, - map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBlseek); return; } @@ -8739,6 +8744,7 @@ void reply_getattrE(struct smb_request *req) int mode; files_struct *fsp; struct timespec create_ts; + NTSTATUS status; START_PROFILE(SMBgetattrE); @@ -8757,8 +8763,9 @@ void reply_getattrE(struct smb_request *req) } /* Do an fstat on this file */ - if(fsp_stat(fsp)) { - reply_nterror(req, map_nt_error_from_unix(errno)); + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBgetattrE); return; } -- 2.17.1 From 384ce064ed1b956186dcf9ce38332b8c62c8f63f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 08:03:53 +0200 Subject: [PATCH 8/9] s3:vfs: streamline vfs_stat_fsp() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher (cherry picked from commit e00e78cfeda99bd5374eff8fb4ba84873e4e46b7) --- source3/smbd/vfs.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 51a4aeb0f225..67f7d6356a2a 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1413,13 +1413,11 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) } else { ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } - if (ret == -1) { - return map_nt_error_from_unix(errno); - } } else { - if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { - return map_nt_error_from_unix(errno); - } + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); + } + if (ret == -1) { + return map_nt_error_from_unix(errno); } return NT_STATUS_OK; } -- 2.17.1 From 9d05f86b48a7f71421ef194b20facc366698c588 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Mon, 9 Sep 2019 08:08:06 +0200 Subject: [PATCH 9/9] vfs: restore stat fields in vfs_stat_fsp() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures we preserve btime, itime and File-ID. As the Durable Handles code calls vfs_stat_fsp() in the DH disconnect function, previously the btime was lost and NOT stored in the cookie. With this change the cookie will store the correct btime (and iflags), which requires us to call dos_mode() in the reconnect function to ensure we pass vfs_default_durable_reconnect_check_stat(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14121 Signed-off-by: Ralph Boehme Reviewed-by: Stefan Metzmacher Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Tue Sep 10 20:22:21 UTC 2019 on sn-devel-184 (cherry picked from commit 95655fe683d499d93f3844ed72ad332ef64adb96) --- selftest/knownfail.d/samba3.smb2.create | 1 - source3/smbd/durable.c | 2 ++ source3/smbd/vfs.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) delete mode 100644 selftest/knownfail.d/samba3.smb2.create diff --git a/selftest/knownfail.d/samba3.smb2.create b/selftest/knownfail.d/samba3.smb2.create deleted file mode 100644 index 89455dacdf0c..000000000000 --- a/selftest/knownfail.d/samba3.smb2.create +++ /dev/null @@ -1 +0,0 @@ -^samba3.smb2.fileid.fileid\(nt4_dc\) diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c index 4aa5a2d619ed..89c4c1e8d144 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -842,6 +842,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } + (void)dos_mode(fsp->conn, fsp->fsp_name); + ok = vfs_default_durable_reconnect_check_stat(&cookie.stat_info, &fsp->fsp_name->st, fsp_str_dbg(fsp)); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 67f7d6356a2a..c8437a0c6c94 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1406,6 +1406,7 @@ int vfs_stat_smb_basename(struct connection_struct *conn, NTSTATUS vfs_stat_fsp(files_struct *fsp) { int ret; + struct stat_ex saved_stat = fsp->fsp_name->st; if(fsp->fh->fd == -1) { if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { @@ -1419,6 +1420,7 @@ NTSTATUS vfs_stat_fsp(files_struct *fsp) if (ret == -1) { return map_nt_error_from_unix(errno); } + update_stat_ex_from_saved_stat(&fsp->fsp_name->st, &saved_stat); return NT_STATUS_OK; } -- 2.17.1