]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: deal with real dirfsps in non_widelink_open()
authorRalph Boehme <slow@samba.org>
Tue, 24 Nov 2020 11:30:28 +0000 (12:30 +0100)
committerRalph Boehme <slow@samba.org>
Wed, 16 Dec 2020 09:08:30 +0000 (09:08 +0000)
If we get a real dirfsp, skip the parent-directory logic. Just pass the dirfsp
to SMB_VFS_OPENAT() which by now supports real dirfsps.

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

index 3dff25ccf8b28fbf93c0a341f1599d6fb3516929..09f05a0451bff33b5d5500e823320602249da7f8 100644 (file)
@@ -663,55 +663,64 @@ static int non_widelink_open(const struct files_struct *dirfsp,
        have_opath = true;
 #endif
 
-       if (fsp->fsp_flags.is_directory) {
-               parent_dir_fname = cp_smb_filename(talloc_tos(), smb_fname);
-               if (parent_dir_fname == NULL) {
-                       saved_errno = errno;
-                       goto out;
+       if (dirfsp == conn->cwd_fsp) {
+               if (fsp->fsp_flags.is_directory) {
+                       parent_dir_fname = cp_smb_filename(talloc_tos(), smb_fname);
+                       if (parent_dir_fname == NULL) {
+                               saved_errno = errno;
+                               goto out;
+                       }
+
+                       smb_fname_rel = synthetic_smb_fname(parent_dir_fname,
+                                                           ".",
+                                                           smb_fname->stream_name,
+                                                           &smb_fname->st,
+                                                           smb_fname->twrp,
+                                                           smb_fname->flags);
+                       if (smb_fname_rel == NULL) {
+                               saved_errno = errno;
+                               goto out;
+                       }
+               } else {
+                       ok = parent_smb_fname(talloc_tos(),
+                                             smb_fname,
+                                             &parent_dir_fname,
+                                             &smb_fname_rel);
+                       if (!ok) {
+                               saved_errno = errno;
+                               goto out;
+                       }
                }
 
-               smb_fname_rel = synthetic_smb_fname(parent_dir_fname,
-                                                   ".",
-                                                   smb_fname->stream_name,
-                                                   &smb_fname->st,
-                                                   smb_fname->twrp,
-                                                   smb_fname->flags);
-               if (smb_fname_rel == NULL) {
-                       saved_errno = errno;
+               oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+               if (oldwd_fname == NULL) {
                        goto out;
                }
-       } else {
-               ok = parent_smb_fname(talloc_tos(),
-                                     smb_fname,
-                                     &parent_dir_fname,
-                                     &smb_fname_rel);
-               if (!ok) {
-                       saved_errno = errno;
+
+               /* Pin parent directory in place. */
+               if (vfs_ChDir(conn, parent_dir_fname) == -1) {
                        goto out;
                }
-       }
 
-       oldwd_fname = vfs_GetWd(talloc_tos(), conn);
-       if (oldwd_fname == NULL) {
-               goto out;
-       }
-
-       /* Pin parent directory in place. */
-       if (vfs_ChDir(conn, parent_dir_fname) == -1) {
-               goto out;
-       }
+               /* 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)) {
+                       saved_errno = map_errno_from_nt_status(status);
+                       goto out;
+               }
 
-       /* 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)) {
-               saved_errno = map_errno_from_nt_status(status);
-               goto out;
+               /* Setup fsp->fsp_name to be relative to cwd */
+               fsp->fsp_name = smb_fname_rel;
+       } else {
+               /*
+                * fsp->fsp_name is unchanged as it is already correctly
+                * relative to conn->cwd.
+                */
+               smb_fname_rel = smb_fname;
        }
 
        flags |= O_NOFOLLOW;
 
-       fsp->fsp_name = smb_fname_rel;
-
        fd = SMB_VFS_OPENAT(conn,
                            dirfsp,
                            smb_fname_rel,
@@ -741,6 +750,7 @@ static int non_widelink_open(const struct files_struct *dirfsp,
                if (ret != 0) {
                        goto out;
                }
+               fsp->fsp_name->st = orig_fsp_name->st;
 
                if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
                        ret = SMB_VFS_CLOSE(fsp);