]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3: VFS: streams_xattr: Use openat_pathref_fsp() to create a smb_fname->fsp (and...
authorJeremy Allison <jra@samba.org>
Tue, 22 Jun 2021 23:49:11 +0000 (16:49 -0700)
committerRalph Boehme <slow@samba.org>
Fri, 25 Jun 2021 15:53:31 +0000 (15:53 +0000)
Use new smb_fname->fsp->base_fsp parameter in get_xattr_size(), change name parameter to NULL.

If openat_pathref_fsp() fails, return the correct error code (thanks Ralph!).

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/modules/vfs_streams_xattr.c

index 37da83ea8cec27780d6c82a017f981e28476d7ff..69528a3685147f9f3c87c3348926dc423ef54415 100644 (file)
@@ -238,6 +238,8 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
        int result = -1;
        char *xattr_name = NULL;
        char *tmp_stream_name = NULL;
+       struct smb_filename *smb_fname_cp = NULL;
+       struct files_struct *fsp = smb_fname->fsp;
 
        if (!is_named_stream(smb_fname)) {
                return SMB_VFS_NEXT_STAT(handle, smb_fname);
@@ -267,23 +269,55 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
        }
 
        /* Augment the base file's stat information before returning. */
-       if (smb_fname->fsp == NULL) {
-               smb_fname->st.st_ex_size = get_xattr_size(handle->conn,
-                                                 NULL,
-                                                 smb_fname,
-                                                 xattr_name);
-       } else {
-               SMB_ASSERT(smb_fname->fsp->base_fsp != NULL);
-               smb_fname->st.st_ex_size = get_xattr_size(handle->conn,
-                                                 smb_fname->fsp->base_fsp,
-                                                 NULL,
-                                                 xattr_name);
+       if (fsp == NULL) {
+               /*
+                * openat_pathref_fsp() checks for the same
+                * filetype as the incoming stat info before allowing
+                * the open, so we must ensure it's correct here.
+                */
+               smb_fname->st.st_ex_mode &= ~S_IFMT;
+               smb_fname->st.st_ex_mode |= S_IFREG;
+
+               /*
+                * openat_pathref_fsp() expects a talloc'ed
+                * smb_filename. stat can be passed a struct
+                * from the stack. Make a talloc'ed copy
+                * so openat_pathref_fsp() can add its
+                * destructor.
+                */
+               smb_fname_cp = cp_smb_filename(talloc_tos(),
+                                              smb_fname);
+               if (smb_fname_cp == NULL) {
+                       TALLOC_FREE(xattr_name);
+                       errno = ENOMEM;
+                       return -1;
+               }
+               status = openat_pathref_fsp(handle->conn->cwd_fsp,
+                                           smb_fname_cp);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DBG_DEBUG("openat_pathref_fsp for %s failed with %s\n",
+                               smb_fname_str_dbg(smb_fname),
+                               nt_errstr(status));
+                       TALLOC_FREE(xattr_name);
+                       TALLOC_FREE(smb_fname_cp);
+                       SET_STAT_INVALID(smb_fname->st);
+                       errno = ENOENT;
+                       return -1;
+               }
+               fsp = smb_fname_cp->fsp;
        }
+
+       SMB_ASSERT(fsp->base_fsp != NULL);
+       smb_fname->st.st_ex_size = get_xattr_size(handle->conn,
+                                         fsp->base_fsp,
+                                         NULL,
+                                         xattr_name);
        if (smb_fname->st.st_ex_size == -1) {
+               TALLOC_FREE(xattr_name);
+               TALLOC_FREE(smb_fname_cp);
                SET_STAT_INVALID(smb_fname->st);
                errno = ENOENT;
-               result = -1;
-               goto fail;
+               return -1;
        }
 
        smb_fname->st.st_ex_ino = hash_inode(&smb_fname->st, xattr_name);
@@ -293,10 +327,9 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
         smb_fname->st.st_ex_blocks =
            smb_fname->st.st_ex_size / STAT_ST_BLOCKSIZE + 1;
 
-       result = 0;
- fail:
        TALLOC_FREE(xattr_name);
-       return result;
+       TALLOC_FREE(smb_fname_cp);
+       return 0;
 }
 
 static int streams_xattr_lstat(vfs_handle_struct *handle,