From 88d9d0dace32887bba455c99ab5401eb85c45cfd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jul 2021 15:00:13 -0700 Subject: [PATCH 1/5] s3: smbd: Allow "smbd async dosmode = yes" to return valid DOS attributes again. We already have a valid smb_fname->fsp, don't drop it when returning from smbd_dirptr_lanman2_entry() to allow it to be reused inside dos_mode_at_send(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758 Signed-off-by: Jeremy Allison --- source3/smbd/trans2.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index c69e48a4a56..b9e2786eda6 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2551,23 +2551,27 @@ NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx, } if (_smb_fname != NULL) { - struct smb_filename *name = NULL; - - name = synthetic_smb_fname(ctx, - fname, - NULL, - &smb_fname->st, - smb_fname->twrp, - 0); - if (name == NULL) { + /* + * smb_fname is already talloc'ed off ctx. + * We just need to make sure we don't return + * any stream_name, and replace base_name + * with fname in case base_name got mangled. + * This allows us to preserve any smb_fname->fsp + * for asynchronous handle lookups. + */ + TALLOC_FREE(smb_fname->stream_name); + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = talloc_strdup(smb_fname, fname); + + if (smb_fname->base_name == NULL) { TALLOC_FREE(smb_fname); TALLOC_FREE(fname); return NT_STATUS_NO_MEMORY; } - *_smb_fname = name; + *_smb_fname = smb_fname; + } else { + TALLOC_FREE(smb_fname); } - - TALLOC_FREE(smb_fname); TALLOC_FREE(fname); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { -- 2.27.0 From bffdcfb70e1d5f3c5e15d8dd85ddd13a77895fab Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jul 2021 11:17:49 -0700 Subject: [PATCH 2/5] s3: VFS: default: Move vfswrap_fgetxattr() before the async versions. We want to re-use this and don't want to have to add forward declarations. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758 Signed-off-by: Jeremy Allison --- source3/modules/vfs_default.c | 60 +++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 102938e332e..e9bd2471556 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -3425,6 +3425,36 @@ static int vfswrap_sys_acl_delete_def_fd(vfs_handle_struct *handle, Extended attribute operations. *****************************************************************/ +static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, + struct files_struct *fsp, + const char *name, + void *value, + size_t size) +{ + int fd = fsp_get_pathref_fd(fsp); + + if (!fsp->fsp_flags.is_pathref) { + return fgetxattr(fd, name, value, size); + } + + if (fsp->fsp_flags.have_proc_fds) { + const char *p = NULL; + char buf[PATH_MAX]; + + p = sys_proc_fd_path(fd, buf, sizeof(buf)); + if (p == NULL) { + return -1; + } + + return getxattr(p, name, value, size); + } + + /* + * This is no longer a handle based call. + */ + return getxattr(fsp->fsp_name->base_name, name, value, size); +} + struct vfswrap_getxattrat_state { struct tevent_context *ev; files_struct *dir_fsp; @@ -3742,36 +3772,6 @@ static ssize_t vfswrap_getxattrat_recv(struct tevent_req *req, return xattr_size; } -static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, - struct files_struct *fsp, - const char *name, - void *value, - size_t size) -{ - int fd = fsp_get_pathref_fd(fsp); - - if (!fsp->fsp_flags.is_pathref) { - return fgetxattr(fd, name, value, size); - } - - if (fsp->fsp_flags.have_proc_fds) { - const char *p = NULL; - char buf[PATH_MAX]; - - p = sys_proc_fd_path(fd, buf, sizeof(buf)); - if (p == NULL) { - return -1; - } - - return getxattr(p, name, value, size); - } - - /* - * This is no longer a handle based call. - */ - return getxattr(fsp->fsp_name->base_name, name, value, size); -} - static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size) { int fd = fsp_get_pathref_fd(fsp); -- 2.27.0 From c25e59a6b4497c9cdfbc3216fc3b0a1c842ab709 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jul 2021 11:35:06 -0700 Subject: [PATCH 3/5] s3: VFS: default: Add 'handle' member to struct vfswrap_getxattrat_state Not yet used. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758 Signed-off-by: Jeremy Allison --- source3/modules/vfs_default.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index e9bd2471556..9d7c0539528 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -3457,6 +3457,7 @@ static ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct vfswrap_getxattrat_state { struct tevent_context *ev; + struct vfs_handle_struct *handle; files_struct *dir_fsp; const struct smb_filename *smb_fname; @@ -3509,6 +3510,7 @@ static struct tevent_req *vfswrap_getxattrat_send( } *state = (struct vfswrap_getxattrat_state) { .ev = ev, + .handle = handle, .dir_fsp = dir_fsp, .smb_fname = smb_fname, }; -- 2.27.0 From ab65e1337e9929a0452de55c476ad2662fc34dd3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jul 2021 11:23:03 -0700 Subject: [PATCH 4/5] s3: VFS: default. In vfswrap_getxattrat_do_sync() always use the pathref fsp. This is always called via a path that mandates smb_fname->fsp is valid. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14758 Signed-off-by: Jeremy Allison --- source3/modules/vfs_default.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 9d7c0539528..cb50342ce67 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -3609,31 +3609,19 @@ static void vfswrap_getxattrat_do_sync(struct tevent_req *req) { struct vfswrap_getxattrat_state *state = tevent_req_data( req, struct vfswrap_getxattrat_state); - char *path = NULL; - char *tofree = NULL; - char pathbuf[PATH_MAX+1]; - ssize_t pathlen; - int err; + struct files_struct *fsp = state->smb_fname->fsp; - pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name, - state->smb_fname->base_name, - pathbuf, - sizeof(pathbuf), - &path, - &tofree); - if (pathlen == -1) { - tevent_req_error(req, ENOMEM); - return; + if (fsp->base_fsp != NULL) { + fsp = fsp->base_fsp; } - state->xattr_size = getxattr(path, - state->xattr_name, - state->xattr_value, - talloc_array_length(state->xattr_value)); - err = errno; - TALLOC_FREE(tofree); + state->xattr_size = vfswrap_fgetxattr(state->handle, + fsp, + state->xattr_name, + state->xattr_value, + talloc_array_length(state->xattr_value)); if (state->xattr_size == -1) { - tevent_req_error(req, err); + tevent_req_error(req, errno); return; } -- 2.27.0 From 148b96fa1c00508e6acc6978c08d13ab043134cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 14 Jul 2021 11:23:54 -0700 Subject: [PATCH 5/5] s3: VFS: default. In vfswrap_getxattrat_do_async() always use the pathref fsp. This is always called via a path that mandates smb_fname->fsp is valid. https://bugzilla.samba.org/show_bug.cgi?id=14758 Signed-off-by: Jeremy Allison --- source3/modules/vfs_default.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index cb50342ce67..aa7dfe3192f 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -3636,6 +3636,11 @@ static void vfswrap_getxattrat_do_async(void *private_data) struct timespec start_time; struct timespec end_time; int ret; + struct files_struct *fsp = state->smb_fname->fsp; + + if (fsp->base_fsp != NULL) { + fsp = fsp->base_fsp; + } PROFILE_TIMESTAMP(&start_time); SMBPROFILE_BYTES_ASYNC_SET_BUSY(state->profile_bytes); @@ -3658,17 +3663,11 @@ static void vfswrap_getxattrat_do_async(void *private_data) goto end_profile; } - ret = fchdir(fsp_get_pathref_fd(state->dir_fsp)); - if (ret == -1) { - state->xattr_size = -1; - state->vfs_aio_state.error = errno; - goto end_profile; - } - - state->xattr_size = getxattr(state->name, - state->xattr_name, - state->xattr_value, - talloc_array_length(state->xattr_value)); + state->xattr_size = vfswrap_fgetxattr(state->handle, + fsp, + state->xattr_name, + state->xattr_value, + talloc_array_length(state->xattr_value)); if (state->xattr_size == -1) { state->vfs_aio_state.error = errno; } -- 2.27.0