The Samba-Bugzilla – Attachment 18389 Details for
Bug 15693
Creation of directories is not atomic regarding acl inheriting and dos modes, this is a problem for rclone as client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Work in progress patches for 4.17
bfixes-tmp417.txt (text/plain), 20.56 KB, created by
Stefan Metzmacher
on 2024-08-02 13:55:39 UTC
(
hide
)
Description:
Work in progress patches for 4.17
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2024-08-02 13:55:39 UTC
Size:
20.56 KB
patch
obsolete
>From d912ae898c5e273d36956dc4fe96d1951bada280 Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Thu, 22 Jun 2023 14:46:01 +0200 >Subject: [PATCH 1/3] smbd: Factor out full_path_from_dirfsp_at_basename() > >Will use this logic in the next patch > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Ralph Boehme <slow@samba.org> >(cherry picked from commit e9040fa42a5539c8bdbf41bd99db74759e966e88) >--- > source3/include/proto.h | 3 +++ > source3/smbd/filename.c | 40 ++++++++++++++++++++++++++-------------- > 2 files changed, 29 insertions(+), 14 deletions(-) > >diff --git a/source3/include/proto.h b/source3/include/proto.h >index 032e7aa33207..30d5aa048596 100644 >--- a/source3/include/proto.h >+++ b/source3/include/proto.h >@@ -736,6 +736,9 @@ NTSTATUS filename_convert_dirfsp( > NTTIME twrp, > struct files_struct **pdirfsp, > struct smb_filename **psmb_name_rel); >+char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx, >+ const struct files_struct *dirfsp, >+ const char *at_base_name); > struct smb_filename *full_path_from_dirfsp_atname( > TALLOC_CTX *mem_ctx, > const struct files_struct *dirfsp, >diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c >index 84e790a24bcf..e05a51c466b3 100644 >--- a/source3/smbd/filename.c >+++ b/source3/smbd/filename.c >@@ -1567,27 +1567,39 @@ next: > goto next; > } > >-/* >- * Build the full path from a dirfsp and dirfsp relative name >- */ >-struct smb_filename *full_path_from_dirfsp_atname( >- TALLOC_CTX *mem_ctx, >- const struct files_struct *dirfsp, >- const struct smb_filename *atname) >+char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx, >+ const struct files_struct *dirfsp, >+ const char *at_base_name) > { >- struct smb_filename *fname = NULL; > char *path = NULL; > > if (dirfsp == dirfsp->conn->cwd_fsp || >- ISDOT(dirfsp->fsp_name->base_name) || >- atname->base_name[0] == '/') >- { >- path = talloc_strdup(mem_ctx, atname->base_name); >+ ISDOT(dirfsp->fsp_name->base_name) || at_base_name[0] == '/') { >+ path = talloc_strdup(mem_ctx, at_base_name); > } else { >- path = talloc_asprintf(mem_ctx, "%s/%s", >+ path = talloc_asprintf(mem_ctx, >+ "%s/%s", > dirfsp->fsp_name->base_name, >- atname->base_name); >+ at_base_name); > } >+ >+ return path; >+} >+ >+/* >+ * Build the full path from a dirfsp and dirfsp relative name >+ */ >+struct smb_filename * >+full_path_from_dirfsp_atname(TALLOC_CTX *mem_ctx, >+ const struct files_struct *dirfsp, >+ const struct smb_filename *atname) >+{ >+ struct smb_filename *fname = NULL; >+ char *path = NULL; >+ >+ path = full_path_from_dirfsp_at_basename(mem_ctx, >+ dirfsp, >+ atname->base_name); > if (path == NULL) { > return NULL; > } >-- >2.34.1 > > >From f2c23918f050175efae2f59d3b4e1b175d5b6c33 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 2 Aug 2024 08:25:16 +0200 >Subject: [PATCH 2/3] TODO: lib/util: let server_id_str_buf_unique() use '%' as > delimiter instead of '/' > >This way the resulting buffer can be used as part of a file/directory >name. > >TODO: impact on server_id_db_init() names.tdb??? > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693 >--- > lib/util/server_id.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > >diff --git a/lib/util/server_id.c b/lib/util/server_id.c >index 690b9ddfbdca..6ec40aa2c26d 100644 >--- a/lib/util/server_id.c >+++ b/lib/util/server_id.c >@@ -90,7 +90,7 @@ size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen) > > if (buflen >= needed) { > memcpy(buf, idbuf.buf, idlen); >- buf[idlen] = '/'; >+ buf[idlen] = '%'; > memcpy(buf + idlen + 1, unique_buf, unique_len+1); > } > >@@ -114,7 +114,7 @@ struct server_id server_id_from_string(uint32_t local_vnn, > */ > > result = templ; >- ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"/%"SCNu64, >+ ret = sscanf(pid_string, "%"SCNu32":%"SCNu64".%"SCNu32"%%%"SCNu64, > &result.vnn, &result.pid, &result.task_id, > &result.unique_id); > if (ret == 4) { >@@ -129,7 +129,7 @@ struct server_id server_id_from_string(uint32_t local_vnn, > } > > result = templ; >- ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"/%"SCNu64, >+ ret = sscanf(pid_string, "%"SCNu32":%"SCNu64"%%%"SCNu64, > &result.vnn, &result.pid, &result.unique_id); > if (ret == 3) { > return result; >@@ -143,7 +143,7 @@ struct server_id server_id_from_string(uint32_t local_vnn, > } > > result = templ; >- ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"/%"SCNu64, >+ ret = sscanf(pid_string, "%"SCNu64".%"SCNu32"%%%"SCNu64, > &result.pid, &result.task_id, &result.unique_id); > if (ret == 3) { > result.vnn = local_vnn; >@@ -159,7 +159,7 @@ struct server_id server_id_from_string(uint32_t local_vnn, > } > > result = templ; >- ret = sscanf(pid_string, "%"SCNu64"/%"SCNu64, >+ ret = sscanf(pid_string, "%"SCNu64"%%%"SCNu64, > &result.pid, &result.unique_id); > if (ret == 2) { > result.vnn = local_vnn; >-- >2.34.1 > > >From 1b8e60ab00fabd69a9a88cd2e91cc164f7676956 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Thu, 1 Aug 2024 14:37:55 +0200 >Subject: [PATCH 3/3] TODO: mkdir_internal tmp_atname > >We could at a test for it using >source3/modules/vfs_delay_inject.c to make the >race more likely to happen. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693 >--- > source3/smbd/dir.c | 56 ++++++++++ > source3/smbd/globals.h | 9 ++ > source3/smbd/open.c | 222 ++++++++++++++++++++++++++++++++++++-- > source3/smbd/proto.h | 1 + > source3/smbd/smb2_reply.c | 2 + > 5 files changed, 283 insertions(+), 7 deletions(-) > >diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c >index 04dfef00d952..3bbfd07c6113 100644 >--- a/source3/smbd/dir.c >+++ b/source3/smbd/dir.c >@@ -1659,11 +1659,67 @@ const char *ReadDirName(struct smb_Dir *dir_hnd, long *poffset, > SeekDir(dir_hnd, *poffset); > > while ((n = vfs_readdirname(conn, dir_hnd->fsp, dir_hnd->dir, sbuf, &talloced))) { >+ int unlink_flags = INT_MAX; > /* Ignore . and .. - we've already returned them. */ > if (ISDOT(n) || ISDOTDOT(n)) { > TALLOC_FREE(talloced); > continue; > } >+ /* >+ * ignore tmp directories, see mkdir_internals() >+ */ >+ if (IS_SMBD_TMPNAME(n, &unlink_flags)) { >+ struct smb_filename *atname = NULL; >+ const char *fp = NULL; >+ int ret; >+ >+ atname = synthetic_smb_fname(talloc_tos(), >+ n, >+ NULL, >+ NULL, >+ 0, >+ 0); >+ if (atname == NULL) { >+ TALLOC_FREE(talloced); >+ continue; >+ } >+ fp = full_path_from_dirfsp_at_basename(atname, >+ dir_hnd->fsp, >+ n); >+ if (fp == NULL) { >+ TALLOC_FREE(atname); >+ TALLOC_FREE(talloced); >+ continue; >+ } >+ >+ if (unlink_flags == INT_MAX) { >+ DBG_NOTICE("ignoring %s\n", fp); >+ TALLOC_FREE(atname); >+ TALLOC_FREE(talloced); >+ continue; >+ } >+ >+ /* >+ * We remove the stale tmpname >+ * as root and ignore any errors >+ */ >+ DBG_NOTICE("unlink stale %s\n", fp); >+ become_root(); >+ ret = SMB_VFS_UNLINKAT(conn, >+ dir_hnd->fsp, >+ atname, >+ unlink_flags); >+ unbecome_root(); >+ if (ret == 0) { >+ DBG_NOTICE("unlinked stale %s\n", fp); >+ } else { >+ DBG_WARNING("failed to unlink stale %s: %s\n", >+ fp, strerror(errno)); >+ } >+ TALLOC_FREE(atname); >+ TALLOC_FREE(talloced); >+ continue; >+ } > *poffset = dir_hnd->offset = SMB_VFS_TELLDIR(conn, dir_hnd->dir); > *ptalloced = talloced; > dir_hnd->file_number++; >diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h >index acf09ca4ac57..1fc5797f3f40 100644 >--- a/source3/smbd/globals.h >+++ b/source3/smbd/globals.h >@@ -933,4 +933,13 @@ struct aio_extra { > bool write_through; > }; > >+#define SMBD_TMPNAME_PREFIX ".::TMPNAME:" >+#define SMBD_TMPDIR_PREFIX SMBD_TMPNAME_PREFIX "D:" >+#define IS_SMBD_TMPNAME_PREFIX(__n) \ >+ unlikely(__n[0] == '.' && __n[1] == ':' && \ >+ strncmp(__n, SMBD_TMPNAME_PREFIX, sizeof(SMBD_TMPNAME_PREFIX) -1) == 0) >+#define IS_SMBD_TMPNAME(__n, __unlink_flags) \ >+ (IS_SMBD_TMPNAME_PREFIX(__n) && \ >+ smbd_is_tmpname(__n, __unlink_flags)) >+ > #endif /* _SOURCE3_SMBD_GLOBALS_H_ */ >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index dbf4e40adf4b..e9de9d4f9ba7 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -4307,6 +4307,61 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > return NT_STATUS_OK; > } > >+bool smbd_is_tmpname(const char *n, int *_unlink_flags) >+{ >+ const char *p = n; >+ int unlink_flags = INT_MAX; >+ struct server_id id; >+ bool exists; >+ >+ if (_unlink_flags != NULL) { >+ *_unlink_flags = INT_MAX; >+ } >+ >+ if (!IS_SMBD_TMPNAME_PREFIX(n)) { >+ return false; >+ } >+ p += sizeof(SMBD_TMPNAME_PREFIX) - 1; >+ switch (p[0]) { >+ case 'D': >+ unlink_flags = AT_REMOVEDIR; >+ break; >+ default: >+ return false; >+ } >+ p += 1; >+ if (p[0] != ':') { >+ return false; >+ } >+ p += 1; >+ >+ id = server_id_from_string(get_my_vnn(), p); >+ if (id.pid == UINT64_MAX) { >+ return false; >+ } >+ if (id.unique_id == 0) { >+ return false; >+ } >+ if (id.unique_id == SERVERID_UNIQUE_ID_NOT_TO_VERIFY) { >+ return false; >+ } >+ >+ if (_unlink_flags == NULL) { >+ return true; >+ } >+ >+ exists = serverid_exists(&id); >+ if (!exists) { >+ /* >+ * let the caller know it's stale >+ * and should be removed >+ */ >+ *_unlink_flags = unlink_flags; >+ } >+ >+ return true; >+} >+ > static NTSTATUS mkdir_internal(connection_struct *conn, > struct smb_filename *parent_dir_fname, /* parent. */ > struct smb_filename *smb_fname_atname, /* atname relative to parent. */ >@@ -4314,6 +4369,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > uint32_t file_attributes, > struct files_struct *fsp) > { >+ TALLOC_CTX *frame = talloc_stackframe(); > const struct loadparm_substitution *lp_sub = > loadparm_s3_global_substitution(); > mode_t mode; >@@ -4321,12 +4377,18 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > bool posix_open = false; > bool need_re_stat = false; > uint32_t access_mask = SEC_DIR_ADD_SUBDIR; >+ struct smb_filename *tmp_atname = NULL; >+ char *orig_dname = NULL; >+ char *tmp_dname = NULL; >+ char tmp_pid_buf[64] = { 0, }; >+ SMB_STRUCT_STAT st; > struct vfs_open_how how = { .flags = O_RDONLY|O_DIRECTORY, }; > int ret; > > if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) { > DEBUG(5,("mkdir_internal: failing share access " > "%s\n", lp_servicename(talloc_tos(), lp_sub, SNUM(conn)))); >+ TALLOC_FREE(frame); > return NT_STATUS_ACCESS_DENIED; > } > >@@ -4347,6 +4409,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > smb_fname_str_dbg(parent_dir_fname), > smb_dname->base_name, > nt_errstr(status)); >+ TALLOC_FREE(frame); > return status; > } > >@@ -4356,12 +4419,78 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > } > } > >+ orig_dname = smb_dname->base_name; >+ >+ server_id_str_buf_unique(messaging_server_id(conn->sconn->msg_ctx), >+ tmp_pid_buf, sizeof(tmp_pid_buf)); >+ >+ tmp_atname = cp_smb_filename(frame, >+ smb_fname_atname); >+ if (tmp_atname == NULL) { >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ TALLOC_FREE(tmp_atname->base_name); >+ tmp_atname->base_name = talloc_asprintf(tmp_atname, >+ "%s%s:%s", >+ SMBD_TMPDIR_PREFIX, >+ tmp_pid_buf, >+ smb_fname_atname->base_name); >+ if (tmp_atname == NULL) { >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ if (!ISDOT(parent_dir_fname->base_name)) { >+ tmp_dname = talloc_asprintf(frame, >+ "%s/%s", >+ parent_dir_fname->base_name, >+ tmp_atname->base_name); >+ if (tmp_dname == NULL) { >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ } else { >+ tmp_dname = talloc_strdup(frame, tmp_atname->base_name); >+ if (tmp_dname == NULL) { >+ TALLOC_FREE(frame); >+ return NT_STATUS_NO_MEMORY; >+ } >+ } >+ >+ DBG_DEBUG("%s: %s\n", __location__, "START"); >+ DBG_DEBUG("parent_dir_fname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(parent_dir_fname), parent_dir_fname, VALID_STAT(parent_dir_fname->st), VALID_STAT_OF_DIR(parent_dir_fname->st)); >+ DBG_DEBUG("parent_dir_fname->fsp[%p][%s] VS[%u] VD[%u]\n", parent_dir_fname->fsp, smb_fname_str_dbg(parent_dir_fname->fsp->fsp_name), VALID_STAT(parent_dir_fname->fsp->fsp_name->st), VALID_STAT_OF_DIR(parent_dir_fname->fsp->fsp_name->st)); >+ DBG_DEBUG("tmp_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(tmp_atname), VALID_STAT(tmp_atname->st), VALID_STAT_OF_DIR(tmp_atname->st)); >+ DBG_DEBUG("smb_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_fname_atname), VALID_STAT(smb_fname_atname->st), VALID_STAT_OF_DIR(smb_fname_atname->st)); >+ DBG_DEBUG("fsp[%p]->name[%s][%p] VS[%u] VD[%u]\n", fsp, smb_fname_str_dbg(fsp->fsp_name), fsp->fsp_name, VALID_STAT(fsp->fsp_name->st), VALID_STAT_OF_DIR(fsp->fsp_name->st)); >+ DBG_DEBUG("smb_dname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_dname), smb_dname, VALID_STAT(smb_dname->st), VALID_STAT_OF_DIR(smb_dname->st)); >+ DBG_DEBUG("smb_dname->fsp[%p][%s] VS[%u] VD[%u]\n", smb_dname->fsp, smb_fname_str_dbg(smb_dname->fsp->fsp_name), VALID_STAT(smb_dname->fsp->fsp_name->st), VALID_STAT_OF_DIR(smb_dname->fsp->fsp_name->st)); >+ >+ { >+ int unlink_flags = 0; >+ bool is = smbd_is_tmpname(tmp_atname->base_name, &unlink_flags); >+ SMB_ASSERT(is); >+ SMB_ASSERT(unlink_flags == INT_MAX); >+ } >+ >+ smb_dname->base_name = tmp_dname; >+ >+ DBG_DEBUG("%s: %s\n", __location__, "AFTER-replace"); >+ DBG_DEBUG("parent_dir_fname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(parent_dir_fname), parent_dir_fname, VALID_STAT(parent_dir_fname->st), VALID_STAT_OF_DIR(parent_dir_fname->st)); >+ DBG_DEBUG("parent_dir_fname->fsp[%p][%s] VS[%u] VD[%u]\n", parent_dir_fname->fsp, smb_fname_str_dbg(parent_dir_fname->fsp->fsp_name), VALID_STAT(parent_dir_fname->fsp->fsp_name->st), VALID_STAT_OF_DIR(parent_dir_fname->fsp->fsp_name->st)); >+ DBG_DEBUG("smb_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_fname_atname), VALID_STAT(smb_fname_atname->st), VALID_STAT_OF_DIR(smb_fname_atname->st)); >+ DBG_DEBUG("fsp[%p]->name[%s][%p] VS[%u] VD[%u]\n", fsp, smb_fname_str_dbg(fsp->fsp_name), fsp->fsp_name, VALID_STAT(fsp->fsp_name->st), VALID_STAT_OF_DIR(fsp->fsp_name->st)); >+ DBG_DEBUG("smb_dname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_dname), smb_dname, VALID_STAT(smb_dname->st), VALID_STAT_OF_DIR(smb_dname->st)); >+ DBG_DEBUG("smb_dname->fsp[%p][%s] VS[%u] VD[%u]\n", smb_dname->fsp, smb_fname_str_dbg(smb_dname->fsp->fsp_name), VALID_STAT(smb_dname->fsp->fsp_name->st), VALID_STAT_OF_DIR(smb_dname->fsp->fsp_name->st)); >+ > ret = SMB_VFS_MKDIRAT(conn, > parent_dir_fname->fsp, >- smb_fname_atname, >+ tmp_atname, > mode); > if (ret != 0) { >- return map_nt_error_from_unix(errno); >+ status = map_nt_error_from_unix(errno); >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto restore_orig; > } > > /* >@@ -4370,11 +4499,19 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > */ > fsp->fsp_flags.is_pathref = true; > >- status = fd_openat(parent_dir_fname->fsp, smb_fname_atname, fsp, &how); >+ status = fd_openat(parent_dir_fname->fsp, tmp_atname, fsp, &how); > if (!NT_STATUS_IS_OK(status)) { >- return status; >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto internal_error; > } > >+ DBG_DEBUG("%s: %s\n", __location__, "AFTER-fd_openat"); >+ DBG_DEBUG("tmp_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(tmp_atname), VALID_STAT(tmp_atname->st), VALID_STAT_OF_DIR(tmp_atname->st)); >+ DBG_DEBUG("smb_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_fname_atname), VALID_STAT(smb_fname_atname->st), VALID_STAT_OF_DIR(smb_fname_atname->st)); >+ DBG_DEBUG("fsp[%p]->name[%s][%p] VS[%u] VD[%u]\n", fsp, smb_fname_str_dbg(fsp->fsp_name), fsp->fsp_name, VALID_STAT(fsp->fsp_name->st), VALID_STAT_OF_DIR(fsp->fsp_name->st)); >+ DBG_DEBUG("smb_dname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_dname), smb_dname, VALID_STAT(smb_dname->st), VALID_STAT_OF_DIR(smb_dname->st)); >+ DBG_DEBUG("smb_dname->fsp[%p][%s] VS[%u] VD[%u]\n", smb_dname->fsp, smb_fname_str_dbg(smb_dname->fsp->fsp_name), VALID_STAT(smb_dname->fsp->fsp_name->st), VALID_STAT_OF_DIR(smb_dname->fsp->fsp_name->st)); >+ > /* Ensure we're checking for a symlink here.... */ > /* We don't want to get caught by a symlink racer. */ > >@@ -4382,13 +4519,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > if (!NT_STATUS_IS_OK(status)) { > DEBUG(2, ("Could not stat directory '%s' just created: %s\n", > smb_fname_str_dbg(smb_dname), nt_errstr(status))); >- return status; >+ goto internal_error; > } > > if (!S_ISDIR(smb_dname->st.st_ex_mode)) { > DEBUG(0, ("Directory '%s' just created is not a directory !\n", > smb_fname_str_dbg(smb_dname))); >- return NT_STATUS_NOT_A_DIRECTORY; >+ status = NT_STATUS_NOT_A_DIRECTORY; >+ goto internal_error; > } > > if (lp_store_dos_attributes(SNUM(conn)) && !posix_open) { >@@ -4433,14 +4571,84 @@ static NTSTATUS mkdir_internal(connection_struct *conn, > if (!NT_STATUS_IS_OK(status)) { > DEBUG(2, ("Could not stat directory '%s' just created: %s\n", > smb_fname_str_dbg(smb_dname), nt_errstr(status))); >- return status; >+ goto internal_error; > } > } > >+ /* >+ * TODO: >+ * >+ * Instead of SMB_VFS_FSTATAT followed by >+ * SMB_VFS_RENAMEAT, we should use >+ * SMB_VFS_RENAMEAT(RENAME_NOREPLACE) with >+ * a fallback for EINVAL to SMB_VFS_RENAMEAT() without >+ * RENAME_NOREPLACE. >+ */ >+ ret = SMB_VFS_FSTATAT(conn, parent_dir_fname->fsp, >+ smb_fname_atname, &st, AT_SYMLINK_NOFOLLOW); >+ if (ret == 0) { >+ status = NT_STATUS_OBJECT_NAME_COLLISION; >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto do_unlink; >+ } >+ if (ret != 0 && errno != ENOENT) { >+ status = map_nt_error_from_unix(errno); >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto do_unlink; >+ } >+ ret = SMB_VFS_RENAMEAT(conn, >+ parent_dir_fname->fsp, >+ tmp_atname, >+ parent_dir_fname->fsp, >+ smb_fname_atname); >+ if (ret != 0) { >+ status = map_nt_error_from_unix(errno); >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto do_unlink; >+ } >+ smb_fname_atname->st = tmp_atname->st; >+ smb_dname->base_name = orig_dname; >+ >+ DBG_DEBUG("%s: %s\n", __location__, "AFTER-RENAMEAT"); >+ DBG_DEBUG("tmp_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(tmp_atname), VALID_STAT(tmp_atname->st), VALID_STAT_OF_DIR(tmp_atname->st)); >+ DBG_DEBUG("smb_atname[%s] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_fname_atname), VALID_STAT(smb_fname_atname->st), VALID_STAT_OF_DIR(smb_fname_atname->st)); >+ DBG_DEBUG("fsp[%p]->name[%s][%p] VS[%u] VD[%u]\n", fsp, smb_fname_str_dbg(fsp->fsp_name), fsp->fsp_name, VALID_STAT(fsp->fsp_name->st), VALID_STAT_OF_DIR(fsp->fsp_name->st)); >+ DBG_DEBUG("smb_dname[%s][%p] VS[%u] VD[%u]\n", smb_fname_str_dbg(smb_dname), smb_dname, VALID_STAT(smb_dname->st), VALID_STAT_OF_DIR(smb_dname->st)); >+ DBG_DEBUG("smb_dname->fsp[%p][%s] VS[%u] VD[%u]\n", smb_dname->fsp, smb_fname_str_dbg(smb_dname->fsp->fsp_name), VALID_STAT(smb_dname->fsp->fsp_name->st), VALID_STAT_OF_DIR(smb_dname->fsp->fsp_name->st)); >+ DBG_DEBUG("%s: %s\n", __location__, "DONE"); >+ > notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME, > smb_dname->base_name); > >+ TALLOC_FREE(frame); > return NT_STATUS_OK; >+ >+internal_error: >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ goto restore_orig; >+ >+do_unlink: >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ ret = SMB_VFS_UNLINKAT(conn, >+ parent_dir_fname->fsp, >+ tmp_atname, >+ AT_REMOVEDIR); >+ if (ret == 0) { >+ status = map_nt_error_from_unix(errno); >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ } else { >+ status = map_nt_error_from_unix(errno); >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ } >+ goto restore_orig; >+ >+restore_orig: >+ DBG_ERR("%s: %s\n", __location__, nt_errstr(status)); >+ SET_STAT_INVALID(smb_fname_atname->st); >+ smb_dname->base_name = orig_dname; >+ SET_STAT_INVALID(smb_dname->st); >+ TALLOC_FREE(frame); >+ return status; > } > > /**************************************************************************** >diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h >index 8075f4e567e3..956a7d3d2141 100644 >--- a/source3/smbd/proto.h >+++ b/source3/smbd/proto.h >@@ -713,6 +713,7 @@ NTSTATUS smbd_check_access_rights_fsp(struct files_struct *dirfsp, > uint32_t access_mask); > NTSTATUS check_parent_access_fsp(struct files_struct *fsp, > uint32_t access_mask); >+bool smbd_is_tmpname(const char *n, int *_unlink_flags); > NTSTATUS fd_openat(const struct files_struct *dirfsp, > struct smb_filename *smb_fname, > files_struct *fsp, >diff --git a/source3/smbd/smb2_reply.c b/source3/smbd/smb2_reply.c >index 2a00d0897b5f..7202065dbedd 100644 >--- a/source3/smbd/smb2_reply.c >+++ b/source3/smbd/smb2_reply.c >@@ -166,6 +166,8 @@ static NTSTATUS check_path_syntax_internal(char *path, > s++; > continue; > } >+ } else if (IS_SMBD_TMPNAME(s, NULL)) { >+ return NT_STATUS_OBJECT_NAME_INVALID; > } > > } >-- >2.34.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
metze
:
review-
Actions:
View
Attachments on
bug 15693
:
18388
|
18389