From 658f0efbeaa70f4e42b823787070791546913998 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 12 Mar 2020 16:52:34 +0100 Subject: [PATCH 1/3] smbd: always flush pending write time update when setting filesize We need to flush a pending write time update even when we're setting the filesize to current filesize. Note that we're already doing it this way in the relevant places listed my dochelp@MS in https://lists.samba.org/archive/cifs-protocol/2019-December/003364.html Cleanup (= Close) SetBasicInfo SetAllocationInfo SetEndOfFileInfo SetValidDataLengthInfo Flush FSCTL_SET_ENCRYPTION FSCTL_OFFLOAD_WRITE Cleanup (= Close): Already implemented by update_write_time_on_close() and friends. SetBasicInfo: Currently doesn't flush pending updates. Fixed by a subsequent commit. SetAllocationInfo: smb_set_file_allocation_info() when setting a file's allocation size. SetEndOfFileInfo: Currently doesn't flush pending updates. Fixed by a subsequent commit. SetValidDataLengthInfo: Not implemented, returns NT_STATUS_NOT_SUPPORTED which seems wrong btw, as SetValidDataLengthInfo IS listed in MS-SMB2 2.2.39. Flush: Currently doesn't flush pending updates. Fixed by subsequent commit. FSCTL_SET_ENCRYPTION: Windows 2016 doesn't flush a pending writetime update, verified with a smbtorture test. FSCTL_OFFLOAD_WRITE: NT_STATUS_NOT_IMPLEMENTED BUG: https://bugzilla.samba.org/show_bug.cgi?id=14150 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (back-ported from commit 79d7d6b9d01b8547f16b74a62926d0b471f18c39) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8164c8fd213..c86e340845a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -6567,6 +6567,13 @@ static NTSTATUS smb_set_file_size(connection_struct *conn, get_file_size_stat(psbuf)); if (size == get_file_size_stat(psbuf)) { + if (fsp == NULL) { + return NT_STATUS_OK; + } + if (!fsp->modified) { + return NT_STATUS_OK; + } + trigger_write_time_update_immediate(fsp); return NT_STATUS_OK; } -- 2.20.1 From 8c079c35828a6be3e17d03efdf696242bf9bbfe4 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 12 Mar 2020 19:23:40 +0100 Subject: [PATCH 2/3] smbd: flush pending writetime update when flushing file Cf the explanations in the previous commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14150 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (back-ported from commit d99d5bf2c6d0a818ef2f3920e0c93fac38761c36) --- source3/smbd/reply.c | 7 +++++++ source3/smbd/smb2_flush.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 65ac729c732..b551d9222df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -5418,6 +5418,10 @@ static struct files_struct *file_sync_one_fn(struct files_struct *fsp, } sync_file(conn, fsp, True /* write through */); + if (fsp->modified) { + trigger_write_time_update_immediate(fsp); + } + return NULL; } @@ -5456,6 +5460,9 @@ void reply_flush(struct smb_request *req) END_PROFILE(SMBflush); return; } + if (fsp->modified) { + trigger_write_time_update_immediate(fsp); + } } reply_outbuf(req, 0, 0); diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 470a8df4944..86dd14844e6 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -112,6 +112,7 @@ static void smbd_smb2_request_flush_done(struct tevent_req *subreq) struct smbd_smb2_flush_state { struct smbd_smb2_request *smb2req; + struct files_struct *fsp; }; static void smbd_smb2_flush_done(struct tevent_req *subreq); @@ -133,6 +134,7 @@ static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx, return NULL; } state->smb2req = smb2req; + state->fsp = fsp; DEBUG(10,("smbd_smb2_flush: %s - %s\n", fsp_str_dbg(fsp), fsp_fnum_dbg(fsp))); @@ -214,6 +216,8 @@ static void smbd_smb2_flush_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( subreq, struct tevent_req); + struct smbd_smb2_flush_state *state = tevent_req_data( + req, struct smbd_smb2_flush_state); int ret; struct vfs_aio_state vfs_aio_state; @@ -223,6 +227,9 @@ static void smbd_smb2_flush_done(struct tevent_req *subreq) tevent_req_nterror(req, map_nt_error_from_unix(vfs_aio_state.error)); return; } + if (state->fsp->modified) { + trigger_write_time_update_immediate(state->fsp); + } tevent_req_done(req); } -- 2.20.1 From 4c8c9158b04b82cda509268fb59cbe126613201d Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 12 Mar 2020 19:23:40 +0100 Subject: [PATCH 3/3] smbd: flush pending writetime update when setting timestamps file Cf the explanations in the previous commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14150 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison (back-ported from commit 7b90fe69a865ae8648b6548eabbcf2fa8237ebd8) --- source3/smbd/reply.c | 4 ++++ source3/smbd/trans2.c | 25 ++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b551d9222df..9736077c8ad 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -8698,6 +8698,10 @@ void reply_setattrE(struct smb_request *req) goto out; } + if (fsp->modified) { + trigger_write_time_update_immediate(fsp); + } + DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u " " createtime=%u\n", fsp_fnum_dbg(fsp), diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c86e340845a..78dabc016ed 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7711,8 +7711,15 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn, DEBUG(10, ("smb_set_file_basic_info: file %s\n", smb_fname_str_dbg(smb_fname))); - return smb_set_file_time(conn, fsp, smb_fname, &ft, - true); + status = smb_set_file_time(conn, fsp, smb_fname, &ft, true); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (fsp != NULL && fsp->modified) { + trigger_write_time_update_immediate(fsp); + } + return NT_STATUS_OK; } /**************************************************************************** @@ -7749,11 +7756,15 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn, return status; } - return smb_set_file_time(conn, - fsp, - smb_fname, - &ft, - true); + status = smb_set_file_time(conn, fsp, smb_fname, &ft, true); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (fsp != NULL && fsp->modified) { + trigger_write_time_update_immediate(fsp); + } + return NT_STATUS_OK; } /**************************************************************************** -- 2.20.1