]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Pass dirfsp instead of a parent filename to unix_mode
authorVolker Lendecke <vl@samba.org>
Thu, 3 Mar 2022 10:52:12 +0000 (11:52 +0100)
committerRalph Boehme <slow@samba.org>
Fri, 4 Mar 2022 17:43:42 +0000 (17:43 +0000)
This converts a STAT (with potential symlink race problems) into an
FSTAT on the O_PATH fd we have for the directory

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/smbd/dosmode.c
source3/smbd/open.c
source3/smbd/proto.h

index 68764b46ac817e0eadaf8fa5c4238a0d9ab3adcd..f434b3875ca166a061f8f1ceec94723ca6949a7e 100644 (file)
@@ -106,7 +106,7 @@ static uint32_t filter_mode_by_protocol(uint32_t mode)
 
 mode_t unix_mode(connection_struct *conn, int dosmode,
                 const struct smb_filename *smb_fname,
-                struct smb_filename *smb_fname_parent)
+                struct files_struct *parent_dirfsp)
 {
        mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
        mode_t dir_mode = 0; /* Mode of the inherit_from directory if
@@ -116,20 +116,24 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
                result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
        }
 
-       if ((smb_fname_parent != NULL) && lp_inherit_permissions(SNUM(conn))) {
+       if ((parent_dirfsp != NULL) && lp_inherit_permissions(SNUM(conn))) {
+               struct stat_ex sbuf = { .st_ex_nlink = 0, };
+               int ret;
+
                DBG_DEBUG("[%s] inheriting from [%s]\n",
                          smb_fname_str_dbg(smb_fname),
-                         smb_fname_str_dbg(smb_fname_parent));
+                         smb_fname_str_dbg(parent_dirfsp->fsp_name));
 
-               if (SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
-                       DBG_ERR("stat failed [%s]: %s\n",
-                               smb_fname_str_dbg(smb_fname_parent),
+               ret = SMB_VFS_FSTAT(parent_dirfsp, &sbuf);
+               if (ret != 0) {
+                       DBG_ERR("fstat failed [%s]: %s\n",
+                               smb_fname_str_dbg(parent_dirfsp->fsp_name),
                                strerror(errno));
                        return(0);      /* *** shouldn't happen! *** */
                }
 
                /* Save for later - but explicitly remove setuid bit for safety. */
-               dir_mode = smb_fname_parent->st.st_ex_mode & ~S_ISUID;
+               dir_mode = sbuf.st_ex_mode & ~S_ISUID;
                DEBUG(2,("unix_mode(%s) inherit mode %o\n",
                         smb_fname_str_dbg(smb_fname), (int)dir_mode));
                /* Clear "result" */
@@ -973,7 +977,11 @@ int file_set_dosmode(connection_struct *conn,
        }
 
        /* Fall back to UNIX modes. */
-       unixmode = unix_mode(conn, dosmode, smb_fname, parent_dir);
+       unixmode = unix_mode(
+               conn,
+               dosmode,
+               smb_fname,
+               parent_dir != NULL ? parent_dir->fsp : NULL);
 
        /* preserve the file type bits */
        mask |= S_IFMT;
index d4fce40d16e9beb1de2f868c42b19933c07ef58e..baae51f157e6d296fc8accb22dd9caaab10f58ae 100644 (file)
@@ -3513,8 +3513,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
 
                /* We add FILE_ATTRIBUTE_ARCHIVE to this as this mode is only used if the file is
                 * created new. */
-               unx_mode = unix_mode(conn, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE,
-                                    smb_fname, parent_dir_fname);
+               unx_mode = unix_mode(
+                       conn,
+                       new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE,
+                       smb_fname,
+                       parent_dir_fname->fsp);
        }
 
        DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
@@ -4269,7 +4272,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                mode = unix_mode(conn,
                                 FILE_ATTRIBUTE_DIRECTORY,
                                 smb_dname,
-                                parent_dir_fname);
+                                parent_dir_fname->fsp);
        }
 
        status = check_parent_access_fsp(parent_dir_fname->fsp, access_mask);
index f880a223f7f1a83c3d7bf8cee31e01b28727fb0a..ac2f7be4bb58a8478cc9ece2f693ad8e62927d7d 100644 (file)
@@ -265,7 +265,7 @@ bool smbd_setup_mdns_registration(struct tevent_context *ev,
 
 mode_t unix_mode(connection_struct *conn, int dosmode,
                 const struct smb_filename *smb_fname,
-                struct smb_filename *smb_fname_parent);
+                struct files_struct *parent_dirfsp);
 uint32_t dos_mode_msdfs(connection_struct *conn,
                      const struct smb_filename *smb_fname);
 uint32_t fdos_mode(struct files_struct *fsp);