From: Volker Lendecke Date: Thu, 3 Mar 2022 10:52:12 +0000 (+0100) Subject: smbd: Pass dirfsp instead of a parent filename to unix_mode X-Git-Tag: tevent-0.12.0~558 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f60ca2e2f35666583f2e8cd11cb507406bb17393;p=thirdparty%2Fsamba.git smbd: Pass dirfsp instead of a parent filename to unix_mode 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 Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 68764b46ac8..f434b3875ca 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -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; diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d4fce40d16e..baae51f157e 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -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); diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index f880a223f7f..ac2f7be4bb5 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -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);