diff --git a/backport-CVE-2021-43566.patch b/backport-CVE-2021-43566.patch new file mode 100644 index 0000000..bf2d45a --- /dev/null +++ b/backport-CVE-2021-43566.patch @@ -0,0 +1,94 @@ +From 9c2e3c72c0cdde31a2a5c2e58ce508070ec151d0 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Tue, 21 Sep 2021 17:38:27 -0700 +Subject: [PATCH] s3: smbd: Fix mkdir race condition allows share escape in + Samba 4.13.X and below: CVE-2021-43566 + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=13979 + +Signed-off-by: Jeremy Allison +--- + source3/smbd/open.c | 43 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 40 insertions(+), 3 deletions(-) + +diff --git a/source3/smbd/open.c b/source3/smbd/open.c +index ef158657684..17163e9ddea 100644 +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -4255,6 +4255,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + uint32_t access_mask = SEC_DIR_ADD_SUBDIR; + int ret; + bool ok; ++ struct smb_filename *oldwd_fname = NULL; ++ struct smb_filename *smb_fname_rel = NULL; + + if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) { + DEBUG(5,("mkdir_internal: failing share access " +@@ -4267,7 +4269,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + ok = parent_smb_fname(talloc_tos(), + smb_dname, + &parent_dir_fname, +- NULL); ++ &smb_fname_rel); + if (!ok) { + return NT_STATUS_NO_MEMORY; + } +@@ -4295,14 +4297,40 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + return status; + } + ++ oldwd_fname = vfs_GetWd(talloc_tos(), conn); ++ if (oldwd_fname == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ /* Pin parent directory in place. */ ++ if (vfs_ChDir(conn, parent_dir_fname) == -1) { ++ status = map_nt_error_from_unix(errno); ++ TALLOC_FREE(oldwd_fname); ++ return status; ++ } ++ ++ /* Ensure the relative path is below the share. */ ++ status = check_reduced_name(conn, parent_dir_fname, smb_fname_rel); ++ if (!NT_STATUS_IS_OK(status)) { ++ goto need_chdir_err; ++ } ++ + ret = SMB_VFS_MKDIRAT(conn, + conn->cwd_fsp, +- smb_dname, ++ smb_fname_rel, + mode); + if (ret != 0) { +- return map_nt_error_from_unix(errno); ++ status = map_nt_error_from_unix(errno); ++ goto need_chdir_err; + } + ++ /* Return to share $cwd. */ ++ ret = vfs_ChDir(conn, oldwd_fname); ++ if (ret == -1) { ++ smb_panic("unable to get back to old directory\n"); ++ } ++ TALLOC_FREE(oldwd_fname); ++ + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + +@@ -4378,6 +4406,15 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + smb_dname->base_name); + + return NT_STATUS_OK; ++ ++ need_chdir_err: ++ ++ ret = vfs_ChDir(conn, oldwd_fname); ++ if (ret == -1) { ++ smb_panic("unable to get back to old directory\n"); ++ } ++ TALLOC_FREE(oldwd_fname); ++ return status; + } + + /**************************************************************************** diff --git a/backport-s3-VFS-Add-SMB_VFS_MKDIRAT.patch b/backport-s3-VFS-Add-SMB_VFS_MKDIRAT.patch new file mode 100644 index 0000000..df9f3a7 --- /dev/null +++ b/backport-s3-VFS-Add-SMB_VFS_MKDIRAT.patch @@ -0,0 +1,243 @@ +From ca3bc7809949c593fd545047a898348d2f5c4da4 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 4 Sep 2019 12:20:46 -0700 +Subject: [PATCH] s3: VFS: Add SMB_VFS_MKDIRAT(). + +Currently identical to SMB_VFS_MKDIR(). + +Next, add to all VFS modules that implement +mkdir and eventually remove mkdir. + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +--- + examples/VFS/skel_opaque.c | 10 ++++++++++ + examples/VFS/skel_transparent.c | 12 ++++++++++++ + source3/include/smbprofile.h | 1 + + source3/include/vfs.h | 13 +++++++++++++ + source3/include/vfs_macros.h | 5 +++++ + source3/modules/vfs_default.c | 28 +++++++++++++++++++++++++++ + source3/modules/vfs_not_implemented.c | 10 ++++++++++ + source3/smbd/vfs.c | 12 ++++++++++++ + 8 files changed, 91 insertions(+) + +diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c +index 5a18268e6f47..a4bfe81966b6 100644 +--- a/examples/VFS/skel_opaque.c ++++ b/examples/VFS/skel_opaque.c +@@ -173,6 +173,15 @@ static int skel_mkdir(vfs_handle_struct *handle, + return -1; + } + ++static int skel_mkdirat(vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode) ++{ ++ errno = ENOSYS; ++ return -1; ++} ++ + static int skel_rmdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { +@@ -1051,6 +1060,7 @@ static struct vfs_fn_pointers skel_opaque_fns = { + .telldir_fn = skel_telldir, + .rewind_dir_fn = skel_rewind_dir, + .mkdir_fn = skel_mkdir, ++ .mkdirat_fn = skel_mkdirat, + .rmdir_fn = skel_rmdir, + .closedir_fn = skel_closedir, + +diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c +index 654c0e6ca851..b827d2ff77cc 100644 +--- a/examples/VFS/skel_transparent.c ++++ b/examples/VFS/skel_transparent.c +@@ -171,6 +171,17 @@ static int skel_mkdir(vfs_handle_struct *handle, + return SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode); + } + ++static int skel_mkdirat(vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode) ++{ ++ return SMB_VFS_NEXT_MKDIRAT(handle, ++ dirfsp, ++ smb_fname, ++ mode); ++} ++ + static int skel_rmdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { +@@ -1333,6 +1344,7 @@ static struct vfs_fn_pointers skel_transparent_fns = { + .telldir_fn = skel_telldir, + .rewind_dir_fn = skel_rewind_dir, + .mkdir_fn = skel_mkdir, ++ .mkdirat_fn = skel_mkdirat, + .rmdir_fn = skel_rmdir, + .closedir_fn = skel_closedir, + +diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h +index fc8945b8bc8b..e1b933ea2dda 100644 +--- a/source3/include/smbprofile.h ++++ b/source3/include/smbprofile.h +@@ -49,6 +49,7 @@ struct tevent_context; + SMBPROFILE_STATS_BASIC(syscall_telldir) \ + SMBPROFILE_STATS_BASIC(syscall_rewinddir) \ + SMBPROFILE_STATS_BASIC(syscall_mkdir) \ ++ SMBPROFILE_STATS_BASIC(syscall_mkdirat) \ + SMBPROFILE_STATS_BASIC(syscall_rmdir) \ + SMBPROFILE_STATS_BASIC(syscall_closedir) \ + SMBPROFILE_STATS_BASIC(syscall_open) \ +diff --git a/source3/include/vfs.h b/source3/include/vfs.h +index 6c741e09919c..9ecc0e554970 100644 +--- a/source3/include/vfs.h ++++ b/source3/include/vfs.h +@@ -701,6 +702,10 @@ struct vfs_fn_pointers { + int (*mkdir_fn)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode); ++ int (*mkdirat_fn)(struct vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode); + int (*rmdir_fn)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname); + int (*closedir_fn)(struct vfs_handle_struct *handle, DIR *dir); +@@ -1208,6 +1213,10 @@ void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle, + int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode); ++int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode); + int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname); + int smb_vfs_call_closedir(struct vfs_handle_struct *handle, +@@ -1655,6 +1664,10 @@ void vfs_not_implemented_rewind_dir(vfs_handle_struct *handle, DIR *dirp); + int vfs_not_implemented_mkdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + mode_t mode); ++int vfs_not_implemented_mkdirat(vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode); + int vfs_not_implemented_rmdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname); + int vfs_not_implemented_closedir(vfs_handle_struct *handle, DIR *dir); +diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h +index c43a7e5a4b53..a093a08ee118 100644 +--- a/source3/include/vfs_macros.h ++++ b/source3/include/vfs_macros.h +@@ -114,6 +114,11 @@ + #define SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode) \ + smb_vfs_call_mkdir((handle)->next,(smb_fname), (mode)) + ++#define SMB_VFS_MKDIRAT(conn, dirfsp, smb_fname, mode) \ ++ smb_vfs_call_mkdirat((conn)->vfs_handles,(dirfsp), (smb_fname), (mode)) ++#define SMB_VFS_NEXT_MKDIRAT(handle, dirfsp, smb_fname, mode) \ ++ smb_vfs_call_mkdirat((handle)->next,(dirfsp), (smb_fname), (mode)) ++ + #define SMB_VFS_RMDIR(conn, smb_fname) \ + smb_vfs_call_rmdir((conn)->vfs_handles, (smb_fname)) + #define SMB_VFS_NEXT_RMDIR(handle, smb_fname) \ +diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c +index bb7eba40df93..2e353e5da75c 100644 +--- a/source3/modules/vfs_default.c ++++ b/source3/modules/vfs_default.c +@@ -517,6 +517,33 @@ static int vfswrap_mkdir(vfs_handle_struct *handle, + return result; + } + ++static int vfswrap_mkdirat(vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode) ++{ ++ int result; ++ const char *path = smb_fname->base_name; ++ char *parent = NULL; ++ ++ START_PROFILE(syscall_mkdirat); ++ ++ SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp); ++ ++ if (lp_inherit_acls(SNUM(handle->conn)) ++ && parent_dirname(talloc_tos(), path, &parent, NULL) ++ && directory_has_default_acl(handle->conn, parent)) { ++ mode = (0777 & lp_directory_mask(SNUM(handle->conn))); ++ } ++ ++ TALLOC_FREE(parent); ++ ++ result = mkdirat(dirfsp->fh->fd, path, mode); ++ ++ END_PROFILE(syscall_mkdirat); ++ return result; ++} ++ + static int vfswrap_rmdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { +@@ -3460,6 +3487,7 @@ static struct vfs_fn_pointers vfs_default_fns = { + .telldir_fn = vfswrap_telldir, + .rewind_dir_fn = vfswrap_rewinddir, + .mkdir_fn = vfswrap_mkdir, ++ .mkdirat_fn = vfswrap_mkdirat, + .rmdir_fn = vfswrap_rmdir, + .closedir_fn = vfswrap_closedir, + +diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c +index 6009abd8d7e2..9fa143a67295 100644 +--- a/source3/modules/vfs_not_implemented.c ++++ b/source3/modules/vfs_not_implemented.c +@@ -170,6 +170,15 @@ int vfs_not_implemented_mkdir(vfs_handle_struct *handle, + return -1; + } + ++int vfs_not_implemented_mkdirat(vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode) ++{ ++ errno = ENOSYS; ++ return -1; ++} ++ + int vfs_not_implemented_rmdir(vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { +@@ -1055,6 +1064,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = { + .telldir_fn = vfs_not_implemented_telldir, + .rewind_dir_fn = vfs_not_implemented_rewind_dir, + .mkdir_fn = vfs_not_implemented_mkdir, ++ .mkdirat_fn = vfs_not_implemented_mkdirat, + .rmdir_fn = vfs_not_implemented_rmdir, + .closedir_fn = vfs_not_implemented_closedir, + +diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c +index a131b3303d58..836fcf41e657 100644 +--- a/source3/smbd/vfs.c ++++ b/source3/smbd/vfs.c +@@ -1588,6 +1588,18 @@ int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, + return handle->fns->mkdir_fn(handle, smb_fname, mode); + } + ++int smb_vfs_call_mkdirat(struct vfs_handle_struct *handle, ++ struct files_struct *dirfsp, ++ const struct smb_filename *smb_fname, ++ mode_t mode) ++{ ++ VFS_FIND(mkdirat); ++ return handle->fns->mkdirat_fn(handle, ++ dirfsp, ++ smb_fname, ++ mode); ++} ++ + int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname) + { diff --git a/backport-s3-VFS-change-connection_struct-cwd_fname-to-cwd_fsp.patch b/backport-s3-VFS-change-connection_struct-cwd_fname-to-cwd_fsp.patch new file mode 100644 index 0000000..3eaa58a --- /dev/null +++ b/backport-s3-VFS-change-connection_struct-cwd_fname-to-cwd_fsp.patch @@ -0,0 +1,435 @@ +From 75f98a19537c4d0791108ebfea82f3f9d4606cb3 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 15 Aug 2019 15:53:32 +0200 +Subject: [PATCH] s3: VFS: change connection_struct cwd_fname to cwd_fsp + +Pair-Programmed-With: Stefan Metzmacher +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/include/vfs.h | 2 +- + source3/modules/vfs_ceph.c | 6 +++--- + source3/modules/vfs_full_audit.c | 4 ++-- + source3/modules/vfs_netatalk.c | 14 ++++++------ + source3/modules/vfs_preopen.c | 2 +- + source3/modules/vfs_virusfilter.c | 18 ++++++++-------- + source3/modules/vfs_virusfilter_clamav.c | 2 +- + source3/modules/vfs_virusfilter_fsav.c | 2 +- + source3/modules/vfs_virusfilter_sophos.c | 2 +- + source3/modules/vfs_virusfilter_utils.c | 2 +- + source3/smbd/conn.c | 15 +++++++++++++ + source3/smbd/service.c | 8 +++---- + source3/smbd/uid.c | 2 +- + source3/smbd/vfs.c | 27 +++++++++++++++--------- + 14 files changed, 64 insertions(+), 42 deletions(-) + +diff --git a/source3/include/vfs.h b/source3/include/vfs.h +index aec9546681be..d3e6ec258c32 100644 +--- a/source3/include/vfs.h ++++ b/source3/include/vfs.h +@@ -475,7 +475,7 @@ typedef struct connection_struct { + enum timestamp_set_resolution ts_res; + char *connectpath; + char *origpath; +- struct smb_filename *cwd_fname; /* Working directory. */ ++ struct files_struct *cwd_fsp; /* Working directory. */ + bool tcon_done; + + struct vfs_handle_struct *vfs_handles; /* for the new plugins */ +diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c +index 28363f003c22..bdf1f5128cf5 100644 +--- a/source3/modules/vfs_ceph.c ++++ b/source3/modules/vfs_ceph.c +@@ -1200,14 +1200,14 @@ static struct smb_filename *cephwrap_realpath(struct vfs_handle_struct *handle, + } else if ((len >= 2) && (path[0] == '.') && (path[1] == '/')) { + if (len == 2) { + r = asprintf(&result, "%s", +- handle->conn->cwd_fname->base_name); ++ handle->conn->cwd_fsp->fsp_name->base_name); + } else { + r = asprintf(&result, "%s/%s", +- handle->conn->cwd_fname->base_name, &path[2]); ++ handle->conn->cwd_fsp->fsp_name->base_name, &path[2]); + } + } else { + r = asprintf(&result, "%s/%s", +- handle->conn->cwd_fname->base_name, path); ++ handle->conn->cwd_fsp->fsp_name->base_name, path); + } + + if (r < 0) { +diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c +index 80d15f25ac6b..7a2e15d59601 100644 +--- a/source3/modules/vfs_full_audit.c ++++ b/source3/modules/vfs_full_audit.c +@@ -680,11 +680,11 @@ static const char *smb_fname_str_do_log(struct connection_struct *conn, + if (!ISDOT(smb_fname->base_name)) { + abs_name = talloc_asprintf(do_log_ctx(), + "%s/%s", +- conn->cwd_fname->base_name, ++ conn->cwd_fsp->fsp_name->base_name, + smb_fname->base_name); + } else { + abs_name = talloc_strdup(do_log_ctx(), +- conn->cwd_fname->base_name); ++ conn->cwd_fsp->fsp_name->base_name); + } + if (abs_name == NULL) { + return ""; +diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c +index 3085cf4c7c9a..ebdf8d249b62 100644 +--- a/source3/modules/vfs_netatalk.c ++++ b/source3/modules/vfs_netatalk.c +@@ -234,7 +234,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, + const char *path = smb_fname->base_name; + char *dpath; + +- if (!handle->conn->cwd_fname->base_name || !path) goto exit_rmdir; ++ if (!handle->conn->cwd_fsp->fsp_name->base_name || !path) goto exit_rmdir; + + /* due to there is no way to change bDeleteVetoFiles variable + * from this module, gotta use talloc stuff.. +@@ -246,7 +246,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle, + goto exit_rmdir; + + if (!(dpath = talloc_asprintf(ctx, "%s/%s%s", +- handle->conn->cwd_fname->base_name, path, add ? "/"APPLEDOUBLE : ""))) ++ handle->conn->cwd_fsp->fsp_name->base_name, path, add ? "/"APPLEDOUBLE : ""))) + goto exit_rmdir; + + atalk_rrmdir(ctx, dpath); +@@ -277,7 +277,7 @@ static int atalk_rename(struct vfs_handle_struct *handle, + return ret; + } + +- if (atalk_build_paths(talloc_tos(), handle->conn->cwd_fname->base_name, oldname, ++ if (atalk_build_paths(talloc_tos(), handle->conn->cwd_fsp->fsp_name->base_name, oldname, + &adbl_path, &orig_path, &adbl_info, + &orig_info) != 0) + goto exit_rename; +@@ -339,7 +339,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, + } + + if (atalk_build_paths(talloc_tos(), +- handle->conn->cwd_fname->base_name, path, ++ handle->conn->cwd_fsp->fsp_name->base_name, path, + &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) + goto exit_unlink; +@@ -376,7 +376,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle, + return ret; + + ret1 = atalk_build_paths(ctx, +- handle->conn->cwd_fname->base_name, ++ handle->conn->cwd_fsp->fsp_name->base_name, + smb_fname->base_name, + &adbl_path, + &orig_path, +@@ -415,7 +415,7 @@ static int atalk_chown(struct vfs_handle_struct *handle, + if (!(ctx = talloc_init("chown_file"))) + return ret; + +- if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name, ++ if (atalk_build_paths(ctx, handle->conn->cwd_fsp->fsp_name->base_name, + smb_fname->base_name, + &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) +@@ -452,7 +452,7 @@ static int atalk_lchown(struct vfs_handle_struct *handle, + if (!(ctx = talloc_init("lchown_file"))) + return ret; + +- if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name, ++ if (atalk_build_paths(ctx, handle->conn->cwd_fsp->fsp_name->base_name, + smb_fname->base_name, + &adbl_path, &orig_path, + &adbl_info, &orig_info) != 0) +diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c +index 4a6816129eda..e7cdf9e47768 100644 +--- a/source3/modules/vfs_preopen.c ++++ b/source3/modules/vfs_preopen.c +@@ -415,7 +415,7 @@ static int preopen_open(vfs_handle_struct *handle, + TALLOC_FREE(state->template_fname); + state->template_fname = talloc_asprintf( + state, "%s/%s", +- fsp->conn->cwd_fname->base_name, smb_fname->base_name); ++ fsp->conn->cwd_fsp->fsp_name->base_name, smb_fname->base_name); + + if (state->template_fname == NULL) { + return res; +diff --git a/source3/modules/vfs_virusfilter.c b/source3/modules/vfs_virusfilter.c +index 0b4bc724f3a3..fcf0c2debc97 100644 +--- a/source3/modules/vfs_virusfilter.c ++++ b/source3/modules/vfs_virusfilter.c +@@ -579,7 +579,7 @@ static virusfilter_action infected_file_action_quarantine( + { + TALLOC_CTX *frame = talloc_stackframe(); + connection_struct *conn = handle->conn; +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + char *fname = fsp->fsp_name->base_name; + const struct smb_filename *smb_fname = fsp->fsp_name; + struct smb_filename *q_smb_fname = NULL; +@@ -696,7 +696,7 @@ static virusfilter_action infected_file_action_rename( + { + TALLOC_CTX *frame = talloc_stackframe(); + connection_struct *conn = handle->conn; +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + char *fname = fsp->fsp_name->base_name; + const struct smb_filename *smb_fname = fsp->fsp_name; + struct smb_filename *q_smb_fname = NULL; +@@ -784,7 +784,7 @@ static virusfilter_action infected_file_action_delete( + unbecome_root(); + if (ret == -1) { + DBG_ERR("Delete [%s/%s] failed: %s\n", +- fsp->conn->cwd_fname->base_name, ++ fsp->conn->cwd_fsp->fsp_name->base_name, + fsp->fsp_name->base_name, + strerror(saved_errno)); + errno = saved_errno; +@@ -837,7 +837,7 @@ static virusfilter_action virusfilter_treat_infected_file( + bool is_cache) + { + connection_struct *conn = handle->conn; +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + char *fname = fsp->fsp_name->base_name; + TALLOC_CTX *mem_ctx = talloc_tos(); + int i; +@@ -937,7 +937,7 @@ static void virusfilter_treat_scan_error( + bool is_cache) + { + connection_struct *conn = handle->conn; +- const char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ const char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + const char *fname = fsp->fsp_name->base_name; + TALLOC_CTX *mem_ctx = talloc_tos(); + char *env_list = NULL; +@@ -1003,7 +1003,7 @@ static virusfilter_result virusfilter_scan( + virusfilter_result scan_result; + char *scan_report = NULL; + const char *fname = fsp->fsp_name->base_name; +- const char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ const char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + struct virusfilter_cache_entry *scan_cache_e = NULL; + bool is_cache = false; + virusfilter_action file_action = VIRUSFILTER_ACTION_DO_NOTHING; +@@ -1138,7 +1138,7 @@ static int virusfilter_vfs_open( + { + TALLOC_CTX *mem_ctx = talloc_tos(); + struct virusfilter_config *config; +- const char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ const char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + virusfilter_result scan_result; + const char *fname = fsp->fsp_name->base_name; + char *dir_name = NULL; +@@ -1435,7 +1435,7 @@ static int virusfilter_vfs_unlink( + int ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname); + struct virusfilter_config *config = NULL; + char *fname = NULL; +- char *cwd_fname = handle->conn->cwd_fname->base_name; ++ char *cwd_fname = handle->conn->cwd_fsp->fsp_name->base_name; + + if (ret != 0 && errno != ENOENT) { + return ret; +@@ -1465,7 +1465,7 @@ static int virusfilter_vfs_rename( + struct virusfilter_config *config = NULL; + char *fname = NULL; + char *dst_fname = NULL; +- char *cwd_fname = handle->conn->cwd_fname->base_name; ++ char *cwd_fname = handle->conn->cwd_fsp->fsp_name->base_name; + + if (ret != 0) { + return ret; +diff --git a/source3/modules/vfs_virusfilter_clamav.c b/source3/modules/vfs_virusfilter_clamav.c +index d0e1fc081b7a..fb93caeded66 100644 +--- a/source3/modules/vfs_virusfilter_clamav.c ++++ b/source3/modules/vfs_virusfilter_clamav.c +@@ -81,7 +81,7 @@ static virusfilter_result virusfilter_clamav_scan( + const struct files_struct *fsp, + char **reportp) + { +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + const char *fname = fsp->fsp_name->base_name; + size_t filepath_len = strlen(cwd_fname) + 1 /* slash */ + strlen(fname); + struct virusfilter_io_handle *io_h = config->io_h; +diff --git a/source3/modules/vfs_virusfilter_fsav.c b/source3/modules/vfs_virusfilter_fsav.c +index bd22ee58bc45..240940c75c89 100644 +--- a/source3/modules/vfs_virusfilter_fsav.c ++++ b/source3/modules/vfs_virusfilter_fsav.c +@@ -301,7 +301,7 @@ static virusfilter_result virusfilter_fsav_scan( + const struct files_struct *fsp, + char **reportp) + { +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + const char *fname = fsp->fsp_name->base_name; + struct virusfilter_io_handle *io_h = config->io_h; + virusfilter_result result = VIRUSFILTER_RESULT_CLEAN; +diff --git a/source3/modules/vfs_virusfilter_sophos.c b/source3/modules/vfs_virusfilter_sophos.c +index 82f9cbce7494..c8cdec5fd7fc 100644 +--- a/source3/modules/vfs_virusfilter_sophos.c ++++ b/source3/modules/vfs_virusfilter_sophos.c +@@ -226,7 +226,7 @@ static virusfilter_result virusfilter_sophos_scan( + const struct files_struct *fsp, + char **reportp) + { +- char *cwd_fname = fsp->conn->cwd_fname->base_name; ++ char *cwd_fname = fsp->conn->cwd_fsp->fsp_name->base_name; + const char *fname = fsp->fsp_name->base_name; + char fileurl[VIRUSFILTER_IO_URL_MAX+1]; + int fileurl_len, fileurl_len2; +diff --git a/source3/modules/vfs_virusfilter_utils.c b/source3/modules/vfs_virusfilter_utils.c +index f56fc6ed5d8b..f1a7a9ba6cbe 100644 +--- a/source3/modules/vfs_virusfilter_utils.c ++++ b/source3/modules/vfs_virusfilter_utils.c +@@ -977,7 +977,7 @@ int virusfilter_shell_set_conn_env( + virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_NAME", + lp_const_servicename(snum)); + virusfilter_env_set(mem_ctx, env_list, "VIRUSFILTER_SERVICE_PATH", +- conn->cwd_fname->base_name); ++ conn->cwd_fsp->fsp_name->base_name); + + client_addr_p = tsocket_address_inet_addr_string( + conn->sconn->remote_address, talloc_tos()); +diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c +index ca973b0d6aa6..6d9ea419f8df 100644 +--- a/source3/smbd/conn.c ++++ b/source3/smbd/conn.c +@@ -90,8 +90,23 @@ connection_struct *conn_new(struct smbd_server_connection *sconn) + TALLOC_FREE(conn); + return NULL; + } ++ conn->cwd_fsp = talloc_zero(conn, struct files_struct); ++ if (conn->cwd_fsp == NULL) { ++ DBG_ERR("talloc_zero failed\n"); ++ TALLOC_FREE(conn); ++ return NULL; ++ } ++ conn->cwd_fsp->fh = talloc_zero(conn->cwd_fsp, struct fd_handle); ++ if (conn->cwd_fsp->fh == NULL) { ++ DBG_ERR("talloc_zero failed\n"); ++ TALLOC_FREE(conn); ++ return NULL; ++ } + conn->sconn = sconn; + conn->force_group_gid = (gid_t)-1; ++ conn->cwd_fsp->fh->fd = -1; ++ conn->cwd_fsp->fnum = FNUM_FIELD_INVALID; ++ conn->cwd_fsp->conn = conn; + + DLIST_ADD(sconn->connections, conn); + sconn->num_connections++; +diff --git a/source3/smbd/service.c b/source3/smbd/service.c +index 732cd237b66e..fa84d78ab3b4 100644 +--- a/source3/smbd/service.c ++++ b/source3/smbd/service.c +@@ -72,16 +72,16 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath) + talloc_free(conn->connectpath); + conn->connectpath = destname; + /* +- * Ensure conn->cwd_fname is initialized. ++ * Ensure conn->cwd_fsp->fsp_name is initialized. + * start as conn->connectpath. + */ +- TALLOC_FREE(conn->cwd_fname); +- conn->cwd_fname = synthetic_smb_fname(conn, ++ TALLOC_FREE(conn->cwd_fsp->fsp_name); ++ conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn, + conn->connectpath, + NULL, + NULL, + 0); +- if (conn->cwd_fname == NULL) { ++ if (conn->cwd_fsp->fsp_name == NULL) { + return false; + } + return true; +diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c +index a4bcb747d37e..53c7aa7b7980 100644 +--- a/source3/smbd/uid.c ++++ b/source3/smbd/uid.c +@@ -581,7 +581,7 @@ static void pop_conn_ctx(void) + if (current_user.done_chdir && ctx_p->need_chdir) { + int ret; + +- ret = vfs_ChDir(ctx_p->conn, ctx_p->conn->cwd_fname); ++ ret = vfs_ChDir(ctx_p->conn, ctx_p->conn->cwd_fsp->fsp_name); + if (ret != 0) { + DBG_ERR("vfs_ChDir() failed!\n"); + smb_panic("vfs_ChDir() failed!\n"); +diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c +index b8b482e758ef..467c3e39db1e 100644 +--- a/source3/smbd/vfs.c ++++ b/source3/smbd/vfs.c +@@ -787,7 +787,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p, + int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname) + { + int ret; +- struct smb_filename *old_cwd = conn->cwd_fname; ++ struct smb_filename *cwd = NULL; + + if (!LastDir) { + LastDir = SMB_STRDUP(""); +@@ -810,14 +810,14 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname) + } + + /* +- * Always replace conn->cwd_fname. We ++ * Always replace conn->cwd_fsp. We + * don't know if it's been modified by + * VFS modules in the stack. + */ + + /* conn cache. */ +- conn->cwd_fname = vfs_GetWd(conn, conn); +- if (conn->cwd_fname == NULL) { ++ cwd = vfs_GetWd(conn, conn); ++ if (cwd == NULL) { + /* + * vfs_GetWd() failed. + * We must be able to read cwd. +@@ -826,7 +826,7 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname) + */ + int saved_errno = errno; + +- if (old_cwd == NULL) { ++ if (conn->cwd_fsp->fsp_name == NULL) { + /* + * Failed on the very first chdir()+getwd() + * for this connection. We can't +@@ -836,11 +836,9 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname) + /* NOTREACHED */ + return -1; + } +- /* Restore original conn->cwd_fname. */ +- conn->cwd_fname = old_cwd; + + /* Return to the previous $cwd. */ +- ret = SMB_VFS_CHDIR(conn, conn->cwd_fname); ++ ret = SMB_VFS_CHDIR(conn, conn->cwd_fsp->fsp_name); + if (ret != 0) { + smb_panic("conn->cwd getwd failed\n"); + /* NOTREACHED */ +@@ -856,9 +854,18 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname) + SAFE_FREE(LastDir); + LastDir = SMB_STRDUP(smb_fname->base_name); + +- DEBUG(4,("vfs_ChDir got %s\n", conn->cwd_fname->base_name)); ++ /* ++ * (Indirect) Callers of vfs_ChDir() may still hold references to the ++ * old conn->cwd_fsp->fsp_name. Move it to talloc_tos(), that way ++ * callers can use it for the lifetime of the SMB request. ++ */ ++ talloc_move(talloc_tos(), &conn->cwd_fsp->fsp_name); ++ ++ conn->cwd_fsp->fsp_name = talloc_move(conn->cwd_fsp, &cwd); ++ conn->cwd_fsp->fh->fd = AT_FDCWD; ++ ++ DBG_INFO("vfs_ChDir got %s\n", fsp_str_dbg(conn->cwd_fsp)); + +- TALLOC_FREE(old_cwd); + return ret; + } + diff --git a/backport-s3-lib-add-parent_smb_fname.patch b/backport-s3-lib-add-parent_smb_fname.patch new file mode 100644 index 0000000..ba04884 --- /dev/null +++ b/backport-s3-lib-add-parent_smb_fname.patch @@ -0,0 +1,101 @@ +From 5fe180e751093bb10f847137f879a961db245689 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 28 Apr 2020 12:55:26 +0200 +Subject: [PATCH] s3/lib: add parent_smb_fname() + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/include/proto.h | 4 +++ + source3/lib/filename_util.c | 63 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 67 insertions(+) + +diff --git a/source3/include/proto.h b/source3/include/proto.h +index 6ac0c3d19350..0fd6e64fee39 100644 +--- a/source3/include/proto.h ++++ b/source3/include/proto.h +@@ -392,6 +392,10 @@ char *myhostname_upper(void); + #include "lib/util_path.h" + bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent, + const char **name); ++bool parent_smb_fname(TALLOC_CTX *mem_ctx, ++ const struct smb_filename *path, ++ struct smb_filename **_parent, ++ struct smb_filename **_name); + bool ms_has_wild(const char *s); + bool ms_has_wild_w(const smb_ucs2_t *s); + bool mask_match(const char *string, const char *pattern, bool is_case_sensitive); +diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c +index 1f2e4d31072f..64677e54e3bd 100644 +--- a/source3/lib/filename_util.c ++++ b/source3/lib/filename_util.c +@@ -228,6 +228,69 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx, + return out; + } + ++/** ++ * Return allocated parent directory and basename of path ++ * ++ * Note: if requesting name, it is returned as talloc child of the ++ * parent. Freeing the parent is thus sufficient to free both. ++ */ ++bool parent_smb_fname(TALLOC_CTX *mem_ctx, ++ const struct smb_filename *path, ++ struct smb_filename **_parent, ++ struct smb_filename **_name) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ struct smb_filename *parent = NULL; ++ struct smb_filename *name = NULL; ++ char *p = NULL; ++ ++ parent = cp_smb_filename(frame, path); ++ if (parent == NULL) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ TALLOC_FREE(parent->stream_name); ++ SET_STAT_INVALID(parent->st); ++ ++ p = strrchr_m(parent->base_name, '/'); /* Find final '/', if any */ ++ if (p == NULL) { ++ TALLOC_FREE(parent->base_name); ++ parent->base_name = talloc_strdup(parent, "."); ++ if (parent->base_name == NULL) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ p = path->base_name; ++ } else { ++ *p = '\0'; ++ p++; ++ } ++ ++ if (_name == NULL) { ++ *_parent = talloc_move(mem_ctx, &parent); ++ TALLOC_FREE(frame); ++ return true; ++ } ++ ++ name = cp_smb_filename(frame, path); ++ if (name == NULL) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ TALLOC_FREE(name->base_name); ++ ++ name->base_name = talloc_strdup(mem_ctx, p); ++ if (name == NULL) { ++ TALLOC_FREE(frame); ++ return false; ++ } ++ ++ *_parent = talloc_move(mem_ctx, &parent); ++ *_name = talloc_move(*_parent, &name); ++ TALLOC_FREE(frame); ++ return true; ++} ++ + static void assert_valid_stream_smb_fname(const struct smb_filename *smb_fname) + { + /* stream_name must always be NULL if there is no stream. */ diff --git a/backport-s3-smbd-Change-mkdir_internal-to-call-SMB_VFS_MKDIRAT.patch b/backport-s3-smbd-Change-mkdir_internal-to-call-SMB_VFS_MKDIRAT.patch new file mode 100644 index 0000000..f20acb1 --- /dev/null +++ b/backport-s3-smbd-Change-mkdir_internal-to-call-SMB_VFS_MKDIRAT.patch @@ -0,0 +1,40 @@ +From 99e04578e35d630930e03ee1120b2a432a0edccd Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Fri, 6 Sep 2019 15:05:36 -0700 +Subject: [PATCH] s3: smbd: Change mkdir_internal() to call SMB_VFS_MKDIRAT(). + +Use conn->cwd_fsp as current fsp. + +No logic change for now. + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +--- + source3/smbd/open.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/source3/smbd/open.c b/source3/smbd/open.c +index c9c9c474472d..e6a1c8327e9f 100644 +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -3776,6 +3776,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + bool posix_open = false; + bool need_re_stat = false; + uint32_t access_mask = SEC_DIR_ADD_SUBDIR; ++ int ret; + + if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) { + DEBUG(5,("mkdir_internal: failing share access " +@@ -3807,7 +3808,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + return status; + } + +- if (SMB_VFS_MKDIR(conn, smb_dname, mode) != 0) { ++ ret = SMB_VFS_MKDIRAT(conn, ++ conn->cwd_fsp, ++ smb_dname, ++ mode); ++ if (ret != 0) { + return map_nt_error_from_unix(errno); + } + diff --git a/backport-smbd-use-parent_smb_fname-in-check_parent_access.patch b/backport-smbd-use-parent_smb_fname-in-check_parent_access.patch new file mode 100644 index 0000000..8938de0 --- /dev/null +++ b/backport-smbd-use-parent_smb_fname-in-check_parent_access.patch @@ -0,0 +1,97 @@ +From 61bf5410f0eeb274a67f426811c2dae921626452 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 28 Apr 2020 16:23:07 +0200 +Subject: [PATCH] smbd: use parent_smb_fname() in check_parent_access() + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/smbd/open.c | 32 ++++++++++---------------------- + 1 file changed, 10 insertions(+), 22 deletions(-) + +diff --git a/source3/smbd/open.c b/source3/smbd/open.c +index ecb46d752155..d2ca2b1c50fd 100644 +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -262,31 +262,19 @@ NTSTATUS check_parent_access(struct connection_struct *conn, + uint32_t access_mask) + { + NTSTATUS status; +- char *parent_dir = NULL; + struct security_descriptor *parent_sd = NULL; + uint32_t access_granted = 0; +- struct smb_filename *parent_smb_fname = NULL; ++ struct smb_filename *parent_dir = NULL; + struct share_mode_lock *lck = NULL; + struct file_id id = {0}; + uint32_t name_hash; + bool delete_on_close_set; + int ret; + TALLOC_CTX *frame = talloc_stackframe(); ++ bool ok; + +- if (!parent_dirname(frame, +- smb_fname->base_name, +- &parent_dir, +- NULL)) { +- status = NT_STATUS_NO_MEMORY; +- goto out; +- } +- +- parent_smb_fname = synthetic_smb_fname(frame, +- parent_dir, +- NULL, +- NULL, +- smb_fname->flags); +- if (parent_smb_fname == NULL) { ++ ok = parent_smb_fname(frame, smb_fname, &parent_dir, NULL); ++ if (!ok) { + status = NT_STATUS_NO_MEMORY; + goto out; + } +@@ -302,7 +290,7 @@ NTSTATUS check_parent_access(struct connection_struct *conn, + } + + status = SMB_VFS_GET_NT_ACL(conn, +- parent_smb_fname, ++ parent_dir, + SECINFO_DACL, + frame, + &parent_sd); +@@ -310,7 +298,7 @@ NTSTATUS check_parent_access(struct connection_struct *conn, + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5,("check_parent_access: SMB_VFS_GET_NT_ACL failed for " + "%s with error %s\n", +- parent_dir, ++ smb_fname_str_dbg(parent_dir), + nt_errstr(status))); + goto out; + } +@@ -334,7 +322,7 @@ NTSTATUS check_parent_access(struct connection_struct *conn, + DEBUG(5,("check_parent_access: access check " + "on directory %s for " + "path %s for mask 0x%x returned (0x%x) %s\n", +- parent_dir, ++ smb_fname_str_dbg(parent_dir), + smb_fname->base_name, + access_mask, + access_granted, +@@ -352,15 +340,15 @@ NTSTATUS check_parent_access(struct connection_struct *conn, + } + + /* Check if the directory has delete-on-close set */ +- ret = SMB_VFS_STAT(conn, parent_smb_fname); ++ ret = SMB_VFS_STAT(conn, parent_dir); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + goto out; + } + +- id = SMB_VFS_FILE_ID_CREATE(conn, &parent_smb_fname->st); ++ id = SMB_VFS_FILE_ID_CREATE(conn, &parent_dir->st); + +- status = file_name_hash(conn, parent_smb_fname->base_name, &name_hash); ++ status = file_name_hash(conn, parent_dir->base_name, &name_hash); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } diff --git a/backport-smbd-use-parent_smb_fname-in-inherit_new_acl.patch b/backport-smbd-use-parent_smb_fname-in-inherit_new_acl.patch new file mode 100644 index 0000000..7db8605 --- /dev/null +++ b/backport-smbd-use-parent_smb_fname-in-inherit_new_acl.patch @@ -0,0 +1,76 @@ +From 3830ba0d5bc34c64e79e492315e41dde10a86e33 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 28 Apr 2020 16:52:09 +0200 +Subject: [PATCH] smbd: use parent_smb_fname() in inherit_new_acl() + +Note: has to rename the variable parent_smb_fname otherwise it conflicts with +the function name. + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/smbd/open.c | 24 ++++++++---------------- + 1 file changed, 8 insertions(+), 16 deletions(-) + +diff --git a/source3/smbd/open.c b/source3/smbd/open.c +index ea7f66f82cf4..63adfabee4c9 100644 +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -4813,7 +4813,6 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn, + static NTSTATUS inherit_new_acl(files_struct *fsp) + { + TALLOC_CTX *frame = talloc_stackframe(); +- char *parent_name = NULL; + struct security_descriptor *parent_desc = NULL; + NTSTATUS status = NT_STATUS_OK; + struct security_descriptor *psd = NULL; +@@ -4831,25 +4830,20 @@ static NTSTATUS inherit_new_acl(files_struct *fsp) + const struct dom_sid *SY_U_sid = NULL; + const struct dom_sid *SY_G_sid = NULL; + size_t size = 0; +- struct smb_filename *parent_smb_fname = NULL; +- +- if (!parent_dirname(frame, fsp->fsp_name->base_name, &parent_name, NULL)) { +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- parent_smb_fname = synthetic_smb_fname(talloc_tos(), +- parent_name, +- NULL, +- NULL, +- fsp->fsp_name->flags); ++ struct smb_filename *parent_dir = NULL; ++ bool ok; + +- if (parent_smb_fname == NULL) { ++ ok = parent_smb_fname(frame, ++ fsp->fsp_name, ++ &parent_dir, ++ NULL); ++ if (!ok) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + + status = SMB_VFS_GET_NT_ACL(fsp->conn, +- parent_smb_fname, ++ parent_dir, + (SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL), + frame, + &parent_desc); +@@ -4901,7 +4895,6 @@ static NTSTATUS inherit_new_acl(files_struct *fsp) + + if (try_builtin_administrators) { + struct unixid ids; +- bool ok; + + ZERO_STRUCT(ids); + ok = sids_to_unixids(&global_sid_Builtin_Administrators, 1, &ids); +@@ -4925,7 +4918,6 @@ static NTSTATUS inherit_new_acl(files_struct *fsp) + + if (try_system) { + struct unixid ids; +- bool ok; + + ZERO_STRUCT(ids); + ok = sids_to_unixids(&global_sid_System, 1, &ids); diff --git a/backport-smbd-use-parent_smb_fname-in-mkdir_internal.patch b/backport-smbd-use-parent_smb_fname-in-mkdir_internal.patch new file mode 100644 index 0000000..effbe2d --- /dev/null +++ b/backport-smbd-use-parent_smb_fname-in-mkdir_internal.patch @@ -0,0 +1,47 @@ +From 90a198bcd0a7c2b76f474de1f95f5dc39882c3ec Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Tue, 28 Apr 2020 16:47:44 +0200 +Subject: [PATCH] smbd: use parent_smb_fname() in mkdir_internal() + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/smbd/open.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/source3/smbd/open.c b/source3/smbd/open.c +index 71be6a4966f3..ea7f66f82cf4 100644 +--- a/source3/smbd/open.c ++++ b/source3/smbd/open.c +@@ -4065,12 +4065,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + uint32_t file_attributes) + { + mode_t mode; ++ struct smb_filename *parent_dir_fname = NULL; + char *parent_dir = NULL; + NTSTATUS status; + bool posix_open = false; + bool need_re_stat = false; + uint32_t access_mask = SEC_DIR_ADD_SUBDIR; + int ret; ++ bool ok; + + if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) { + DEBUG(5,("mkdir_internal: failing share access " +@@ -4078,10 +4080,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn, + return NT_STATUS_ACCESS_DENIED; + } + +- if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir, +- NULL)) { ++ ok = parent_smb_fname(talloc_tos(), ++ smb_dname, ++ &parent_dir_fname, ++ NULL); ++ if (!ok) { + return NT_STATUS_NO_MEMORY; + } ++ parent_dir = parent_dir_fname->base_name; + + if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) { + posix_open = true; diff --git a/backport-vfs_full_audit-pass-conn-to-smb_fname_str_do_log.patch b/backport-vfs_full_audit-pass-conn-to-smb_fname_str_do_log.patch new file mode 100644 index 0000000..2a58e65 --- /dev/null +++ b/backport-vfs_full_audit-pass-conn-to-smb_fname_str_do_log.patch @@ -0,0 +1,166 @@ +From b535f78897eb5989666501f9543df478af420ecc Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 15 Aug 2019 14:43:07 +0200 +Subject: [PATCH] vfs_full_audit: pass conn to smb_fname_str_do_log() + +Signed-off-by: Ralph Boehme +Reviewed-by: Jeremy Allison +--- + source3/modules/vfs_full_audit.c | 36 ++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c +index bc644c8f8ed4..80d15f25ac6b 100644 +--- a/source3/modules/vfs_full_audit.c ++++ b/source3/modules/vfs_full_audit.c +@@ -658,7 +658,7 @@ static void do_log(vfs_op_type op, bool success, vfs_handle_struct *handle, + /** + * Return a string using the do_log_ctx() + */ +-static const char *smb_fname_str_do_log(const struct smb_filename *cwd, ++static const char *smb_fname_str_do_log(struct connection_struct *conn, + const struct smb_filename *smb_fname) + { + char *fname = NULL; +@@ -680,11 +680,11 @@ static const char *smb_fname_str_do_log(const struct smb_filename *cwd, + if (!ISDOT(smb_fname->base_name)) { + abs_name = talloc_asprintf(do_log_ctx(), + "%s/%s", +- cwd->base_name, ++ conn->cwd_fname->base_name, + smb_fname->base_name); + } else { + abs_name = talloc_strdup(do_log_ctx(), +- cwd->base_name); ++ conn->cwd_fname->base_name); + } + if (abs_name == NULL) { + return ""; +@@ -705,7 +705,7 @@ static const char *smb_fname_str_do_log(const struct smb_filename *cwd, + */ + static const char *fsp_str_do_log(const struct files_struct *fsp) + { +- return smb_fname_str_do_log(fsp->conn->cwd_fname, fsp->fsp_name); ++ return smb_fname_str_do_log(fsp->conn, fsp->fsp_name); + } + + /* Implementation of vfs_ops. Pass everything on to the default +@@ -1044,7 +1044,7 @@ static int smb_full_audit_open(vfs_handle_struct *handle, + + do_log(SMB_VFS_OP_OPEN, (result >= 0), handle, "%s|%s", + ((flags & O_WRONLY) || (flags & O_RDWR))?"w":"r", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -1119,7 +1119,7 @@ static NTSTATUS smb_full_audit_create_file(vfs_handle_struct *handle, + "0x%x|%s|%s|%s", access_mask, + create_options & FILE_DIRECTORY_FILE ? "dir" : "file", + str_create_disposition, +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -1358,8 +1358,8 @@ static int smb_full_audit_rename(vfs_handle_struct *handle, + result = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); + + do_log(SMB_VFS_OP_RENAME, (result >= 0), handle, "%s|%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname_src), +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname_dst)); ++ smb_fname_str_do_log(handle->conn, smb_fname_src), ++ smb_fname_str_do_log(handle->conn, smb_fname_dst)); + + return result; + } +@@ -1441,7 +1441,7 @@ static int smb_full_audit_stat(vfs_handle_struct *handle, + result = SMB_VFS_NEXT_STAT(handle, smb_fname); + + do_log(SMB_VFS_OP_STAT, (result >= 0), handle, "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -1467,7 +1467,7 @@ static int smb_full_audit_lstat(vfs_handle_struct *handle, + result = SMB_VFS_NEXT_LSTAT(handle, smb_fname); + + do_log(SMB_VFS_OP_LSTAT, (result >= 0), handle, "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -1493,7 +1493,7 @@ static int smb_full_audit_unlink(vfs_handle_struct *handle, + result = SMB_VFS_NEXT_UNLINK(handle, smb_fname); + + do_log(SMB_VFS_OP_UNLINK, (result >= 0), handle, "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -1629,7 +1629,7 @@ static int smb_full_audit_ntimes(vfs_handle_struct *handle, + (result >= 0), + handle, + "%s|%s|%s|%s|%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname), ++ smb_fname_str_do_log(handle->conn, smb_fname), + create_time_str, + atime_str, + mtime_str, +@@ -2065,7 +2065,7 @@ static NTSTATUS smb_full_audit_get_compression(vfs_handle_struct *handle, + do_log(SMB_VFS_OP_GET_COMPRESSION, NT_STATUS_IS_OK(result), handle, + "%s", + (fsp ? fsp_str_do_log(fsp) : +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname))); ++ smb_fname_str_do_log(handle->conn, smb_fname))); + + return result; + } +@@ -2096,7 +2096,7 @@ static NTSTATUS smb_full_audit_readdir_attr(struct vfs_handle_struct *handle, + status = SMB_VFS_NEXT_READDIR_ATTR(handle, fname, mem_ctx, pattr_data); + + do_log(SMB_VFS_OP_READDIR_ATTR, NT_STATUS_IS_OK(status), handle, "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, fname)); ++ smb_fname_str_do_log(handle->conn, fname)); + + return status; + } +@@ -2116,7 +2116,7 @@ static NTSTATUS smb_full_audit_get_dos_attributes( + NT_STATUS_IS_OK(status), + handle, + "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return status; + } +@@ -2277,7 +2277,7 @@ static NTSTATUS smb_full_audit_set_dos_attributes( + NT_STATUS_IS_OK(status), + handle, + "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ smb_fname_str_do_log(handle->conn, smb_fname)); + + return status; + } +@@ -2330,7 +2330,7 @@ static NTSTATUS smb_full_audit_get_nt_acl(vfs_handle_struct *handle, + mem_ctx, ppdesc); + + do_log(SMB_VFS_OP_GET_NT_ACL, NT_STATUS_IS_OK(result), handle, +- "%s", smb_fname_str_do_log(handle->conn->cwd_fname, smb_fname)); ++ "%s", smb_fname_str_do_log(handle->conn, smb_fname)); + + return result; + } +@@ -2377,7 +2377,7 @@ static NTSTATUS smb_full_audit_audit_file(struct vfs_handle_struct *handle, + + do_log(SMB_VFS_OP_AUDIT_FILE, NT_STATUS_IS_OK(result), handle, + "%s", +- smb_fname_str_do_log(handle->conn->cwd_fname, file)); ++ smb_fname_str_do_log(handle->conn, file)); + + return result; + } diff --git a/samba.spec b/samba.spec index 1b8f7bd..91a708c 100644 --- a/samba.spec +++ b/samba.spec @@ -49,7 +49,7 @@ Name: samba Version: 4.11.12 -Release: 7 +Release: 8 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -168,6 +168,15 @@ Patch6239: backport-0003-CVE-2021-3738-s4-rpc_server-dnsserver-make-use-of Patch6240: backport-0004-CVE-2021-3738-s4-rpc_server-lsa-make-use-of-dcesrv_s.patch Patch6241: backport-0005-CVE-2021-3738-s4-rpc_server-netlogon-make-use-of-dce.patch Patch6242: backport-0006-CVE-2021-3738-s4-rpc_server-samr-make-use-of-dcesrv_.patch +Patch6243: backport-s3-lib-add-parent_smb_fname.patch +Patch6244: backport-smbd-use-parent_smb_fname-in-check_parent_access.patch +Patch6245: backport-smbd-use-parent_smb_fname-in-inherit_new_acl.patch +Patch6246: backport-s3-VFS-Add-SMB_VFS_MKDIRAT.patch +Patch6247: backport-vfs_full_audit-pass-conn-to-smb_fname_str_do_log.patch +Patch6248: backport-s3-VFS-change-connection_struct-cwd_fname-to-cwd_fsp.patch +Patch6249: backport-s3-smbd-Change-mkdir_internal-to-call-SMB_VFS_MKDIRAT.patch +Patch6250: backport-smbd-use-parent_smb_fname-in-mkdir_internal.patch +Patch6251: backport-CVE-2021-43566.patch BuildRequires: avahi-devel cups-devel dbus-devel docbook-style-xsl e2fsprogs-devel gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel @@ -3155,6 +3164,21 @@ fi %{_mandir}/man* %changelog +* Thu Jan 20 2022 gaihuiying - 4.11.12-8 +- Type:cves +- ID:CVE-2021-43566 +- SUG:NA +- DESC:backport patches to fix CVE-2021-43566: + s3/lib: add parent_smb_fname function + smbd: use parent_smb_fname in check_parent_access + smbd: use parent_smb_fname in inherit_new_acl + s3/VFS: Add SMB_VFS_MKDIRAT + vfs_full_audit: pass conn to smb_fname_str_do_log + s3/VFS: change connection_struct cwd_fname to cwd_fsp + s3/smbd: Change mkdir_internal to call SMB_VFS_MKDIRAT + smbd: use parent_smb_fname in mkdir_internal + fix CVE-2021-43566 + * Thu Dec 09 2021 xihaochen - 4.11.12-7 - Type:cves - ID:CVE-2020-25717,CVE-2020-25718,CVE-2020-25719,CVE-2020-25721,CVE-2020-25722,CVE-2016-2124,CVE-2021-3738