2010-01-05 12:42:38 +03:00
/*
* Module to work around a bug in Linux XFS :
* http : //oss.sgi.com/bugzilla/show_bug.cgi?id=280
*
* Copyright ( c ) Volker Lendecke 2010
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2010-01-05 12:42:38 +03:00
2019-09-05 20:15:18 +03:00
static int linux_xfs_sgid_mkdirat ( vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
mode_t mode )
{
2020-04-28 16:01:59 +03:00
struct smb_filename * dname = NULL ;
struct smb_filename * fname = NULL ;
2019-09-05 20:15:18 +03:00
int mkdir_res ;
int res ;
2021-05-26 21:07:53 +03:00
NTSTATUS status ;
2019-09-05 20:15:18 +03:00
DEBUG ( 10 , ( " Calling linux_xfs_sgid_mkdirat(%s) \n " ,
smb_fname - > base_name ) ) ;
mkdir_res = SMB_VFS_NEXT_MKDIRAT ( handle ,
dirfsp ,
smb_fname ,
mode ) ;
if ( mkdir_res = = - 1 ) {
DEBUG ( 10 , ( " SMB_VFS_NEXT_MKDIRAT returned error: %s \n " ,
strerror ( errno ) ) ) ;
return mkdir_res ;
}
2020-12-14 17:49:15 +03:00
fname = full_path_from_dirfsp_atname ( talloc_tos ( ) ,
dirfsp ,
smb_fname ) ;
if ( fname = = NULL ) {
return - 1 ;
}
2021-05-26 21:07:53 +03:00
status = SMB_VFS_PARENT_PATHNAME ( handle - > conn ,
talloc_tos ( ) ,
fname ,
& dname ,
NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DBG_WARNING ( " SMB_VFS_PARENT_PATHNAME() failed with %s \n " ,
nt_errstr ( status ) ) ;
2019-09-05 20:15:18 +03:00
/* return success, we did the mkdir */
return mkdir_res ;
}
2020-04-28 16:01:59 +03:00
res = SMB_VFS_NEXT_STAT ( handle , dname ) ;
2019-09-05 20:15:18 +03:00
if ( res = = - 1 ) {
2020-04-28 16:01:59 +03:00
DBG_DEBUG ( " NEXT_STAT(%s) failed: %s \n " ,
smb_fname_str_dbg ( dname ) ,
strerror ( errno ) ) ;
2019-09-05 20:15:18 +03:00
/* return success, we did the mkdir */
return mkdir_res ;
}
2020-04-28 16:01:59 +03:00
if ( ( dname - > st . st_ex_mode & S_ISGID ) = = 0 ) {
2019-09-05 20:15:18 +03:00
/* No SGID to inherit */
DEBUG ( 10 , ( " No SGID to inherit \n " ) ) ;
2020-04-28 16:01:59 +03:00
TALLOC_FREE ( dname ) ;
2019-09-05 20:15:18 +03:00
return mkdir_res ;
}
2020-04-28 16:01:59 +03:00
TALLOC_FREE ( dname ) ;
2019-09-05 20:15:18 +03:00
2020-04-28 16:01:59 +03:00
res = SMB_VFS_NEXT_STAT ( handle , fname ) ;
2019-09-05 20:15:18 +03:00
if ( res = = - 1 ) {
2020-04-28 16:01:59 +03:00
DBG_NOTICE ( " Could not stat just created dir %s: %s \n " ,
smb_fname_str_dbg ( fname ) ,
strerror ( errno ) ) ;
2019-09-05 20:15:18 +03:00
/* return success, we did the mkdir */
2020-04-28 16:01:59 +03:00
TALLOC_FREE ( fname ) ;
2019-09-05 20:15:18 +03:00
return mkdir_res ;
}
2020-04-28 16:01:59 +03:00
fname - > st . st_ex_mode | = S_ISGID ;
fname - > st . st_ex_mode & = ~ S_IFDIR ;
2019-09-05 20:15:18 +03:00
/*
* Yes , we have to do this as root . If you do it as
* non - privileged user , XFS on Linux will just ignore us and
* return success . What can you do . . .
*/
become_root ( ) ;
2021-04-08 13:24:04 +03:00
res = SMB_VFS_NEXT_FCHMOD ( handle , smb_fname - > fsp , fname - > st . st_ex_mode ) ;
2019-09-05 20:15:18 +03:00
unbecome_root ( ) ;
if ( res = = - 1 ) {
2020-04-28 16:01:59 +03:00
DBG_NOTICE ( " CHMOD(%s, %o) failed: %s \n " ,
smb_fname_str_dbg ( fname ) ,
( int ) fname - > st . st_ex_mode ,
strerror ( errno ) ) ;
2019-09-05 20:15:18 +03:00
/* return success, we did the mkdir */
2020-04-28 16:01:59 +03:00
TALLOC_FREE ( fname ) ;
2019-09-05 20:15:18 +03:00
return mkdir_res ;
}
2020-04-28 16:01:59 +03:00
TALLOC_FREE ( fname ) ;
2019-09-05 20:15:18 +03:00
return mkdir_res ;
}
2010-01-05 12:42:38 +03:00
static struct vfs_fn_pointers linux_xfs_sgid_fns = {
2019-09-05 20:15:18 +03:00
. mkdirat_fn = linux_xfs_sgid_mkdirat ,
2010-01-05 12:42:38 +03:00
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_linux_xfs_sgid_init ( TALLOC_CTX * ctx )
2010-01-05 12:42:38 +03:00
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" linux_xfs_sgid " , & linux_xfs_sgid_fns ) ;
}