]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: use pathref fsp in change_dir_owner_to_parent()
authorRalph Boehme <slow@samba.org>
Mon, 14 Dec 2020 10:20:46 +0000 (11:20 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 17 Dec 2020 18:56:29 +0000 (18:56 +0000)
Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/open.c

index fdbcb7c206c6ad6c1062eaf63803bfc83c9c71d3..20f39ee24144ab418ae4ac21c99535b43b563376 100644 (file)
@@ -1023,117 +1023,50 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
                                        struct smb_filename *smb_dname,
                                        SMB_STRUCT_STAT *psbuf)
 {
-       struct smb_filename *smb_fname_cwd = NULL;
-       struct smb_filename *saved_dir_fname = NULL;
-       TALLOC_CTX *ctx = talloc_tos();
-       NTSTATUS status = NT_STATUS_OK;
        int ret;
 
        ret = SMB_VFS_STAT(conn, smb_fname_parent);
        if (ret == -1) {
-               status = map_nt_error_from_unix(errno);
                DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
                         "directory %s. Error was %s\n",
                         smb_fname_str_dbg(smb_fname_parent),
                         strerror(errno)));
-               goto out;
-       }
-
-       /* We've already done an lstat into psbuf, and we know it's a
-          directory. If we can cd into the directory and the dev/ino
-          are the same then we can safely chown without races as
-          we're locking the directory in place by being in it.  This
-          should work on any UNIX (thanks tridge :-). JRA.
-       */
-
-       saved_dir_fname = vfs_GetWd(ctx,conn);
-       if (!saved_dir_fname) {
-               status = map_nt_error_from_unix(errno);
-               DEBUG(0,("change_dir_owner_to_parent: failed to get "
-                        "current working directory. Error was %s\n",
-                        strerror(errno)));
-               goto out;
-       }
-
-       /* Chdir into the new path. */
-       if (vfs_ChDir(conn, smb_dname) == -1) {
-               status = map_nt_error_from_unix(errno);
-               DEBUG(0,("change_dir_owner_to_parent: failed to change "
-                        "current working directory to %s. Error "
-                        "was %s\n", smb_dname->base_name, strerror(errno) ));
-               goto chdir;
-       }
-
-       smb_fname_cwd = synthetic_smb_fname(ctx,
-                                           ".",
-                                           NULL,
-                                           NULL,
-                                           smb_dname->twrp,
-                                           0);
-       if (smb_fname_cwd == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto chdir;
-       }
-
-       ret = SMB_VFS_STAT(conn, smb_fname_cwd);
-       if (ret == -1) {
-               status = map_nt_error_from_unix(errno);
-               DEBUG(0,("change_dir_owner_to_parent: failed to stat "
-                        "directory '.' (%s) Error was %s\n",
-                        smb_dname->base_name, strerror(errno)));
-               goto chdir;
-       }
-
-       /* Ensure we're pointing at the same place. */
-       if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev ||
-           smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino) {
-               DEBUG(0,("change_dir_owner_to_parent: "
-                        "device/inode on directory %s changed. "
-                        "Refusing to chown !\n",
-                       smb_dname->base_name ));
-               status = NT_STATUS_ACCESS_DENIED;
-               goto chdir;
+               return map_nt_error_from_unix(errno);
        }
 
-       if (smb_fname_parent->st.st_ex_uid == smb_fname_cwd->st.st_ex_uid) {
+       if (smb_fname_parent->st.st_ex_uid == smb_dname->st.st_ex_uid) {
                /* Already this uid - no need to change. */
                DEBUG(10,("change_dir_owner_to_parent: directory %s "
                        "is already owned by uid %d\n",
                        smb_dname->base_name,
-                       (int)smb_fname_cwd->st.st_ex_uid ));
-               status = NT_STATUS_OK;
-               goto chdir;
+                       (int)smb_dname->st.st_ex_uid ));
+               return NT_STATUS_OK;
        }
 
        become_root();
-       ret = SMB_VFS_LCHOWN(conn,
-                       smb_fname_cwd,
-                       smb_fname_parent->st.st_ex_uid,
-                       (gid_t)-1);
+       ret = SMB_VFS_FCHOWN(smb_dname->fsp,
+                            smb_fname_parent->st.st_ex_uid,
+                            (gid_t)-1);
        unbecome_root();
        if (ret == -1) {
-               status = map_nt_error_from_unix(errno);
                DEBUG(10,("change_dir_owner_to_parent: failed to chown "
                          "directory %s to parent directory uid %u. "
                          "Error was %s\n",
                          smb_dname->base_name,
                          (unsigned int)smb_fname_parent->st.st_ex_uid,
                          strerror(errno) ));
-       } else {
-               DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
-                       "directory %s to parent directory uid %u.\n",
-                       smb_dname->base_name,
-                       (unsigned int)smb_fname_parent->st.st_ex_uid ));
-               /* Ensure the uid entry is updated. */
-               psbuf->st_ex_uid = smb_fname_parent->st.st_ex_uid;
+               return map_nt_error_from_unix(errno);
        }
 
- chdir:
-       vfs_ChDir(conn, saved_dir_fname);
- out:
-       TALLOC_FREE(saved_dir_fname);
-       TALLOC_FREE(smb_fname_cwd);
-       return status;
+       DBG_DEBUG("changed ownership of new "
+                 "directory %s to parent directory uid %u.\n",
+                 smb_dname->base_name,
+                 (unsigned int)smb_fname_parent->st.st_ex_uid);
+
+       /* Ensure the uid entry is updated. */
+       psbuf->st_ex_uid = smb_fname_parent->st.st_ex_uid;
+
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************