]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs: Fix streams_depot_lstat()
authorVolker Lendecke <vl@samba.org>
Thu, 2 Jan 2025 08:37:32 +0000 (09:37 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 23 Jan 2025 23:08:38 +0000 (23:08 +0000)
When passing NULL as base_sbuf to stream_smb_fname(), it uses
SMB_VFS_NEXT_STAT() to find the right stream directory. This will
potentially dereference the last symlink. Make sure that in
streams_depot_lstat() this is not done.

Also, the current version did not return the stat struct at all.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_streams_depot.c

index d2b8a02431fce85c59cc72c642c715ca7e7d7899..cc69f7f21edbad16df465d92d56d38ec50b2c526 100644 (file)
@@ -623,6 +623,7 @@ static int streams_depot_lstat(vfs_handle_struct *handle,
                               struct smb_filename *smb_fname)
 {
        struct smb_filename *smb_fname_stream = NULL;
+       struct smb_filename *base_fname = NULL;
        NTSTATUS status;
        int ret = -1;
 
@@ -633,9 +634,20 @@ static int streams_depot_lstat(vfs_handle_struct *handle,
                return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
        }
 
-       /* Stat the actual stream now. */
+       base_fname = cp_smb_filename_nostream(talloc_tos(), smb_fname);
+       if (base_fname == NULL) {
+               errno = ENOMEM;
+               goto done;
+       }
+
+       ret = SMB_VFS_NEXT_LSTAT(handle, base_fname);
+       if (ret == -1) {
+               goto done;
+       }
+
+       /* lstat the actual stream now. */
        status = stream_smb_fname(
-               handle, NULL, smb_fname, &smb_fname_stream, false);
+               handle, &base_fname->st, smb_fname, &smb_fname_stream, false);
        if (!NT_STATUS_IS_OK(status)) {
                ret = -1;
                errno = map_errno_from_nt_status(status);
@@ -644,8 +656,17 @@ static int streams_depot_lstat(vfs_handle_struct *handle,
 
        ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_stream);
 
+       if (ret == 0) {
+               smb_fname->st = smb_fname_stream->st;
+       }
+
  done:
-       TALLOC_FREE(smb_fname_stream);
+       {
+               int err = errno;
+               TALLOC_FREE(smb_fname_stream);
+               TALLOC_FREE(base_fname);
+               errno = err;
+       }
        return ret;
 }