@@ -97,6 +97,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
9797		return  - ENOENT ;
9898	}
9999
100+ 	err  =  mnt_want_write (parent_path -> mnt );
101+ 	if  (err ) {
102+ 		path_put (parent_path );
103+ 		putname (filename );
104+ 		return  - ENOENT ;
105+ 	}
106+ 
100107	inode_lock_nested (parent_path -> dentry -> d_inode , I_MUTEX_PARENT );
101108	d  =  lookup_one_qstr_excl (& last , parent_path -> dentry , 0 );
102109	if  (IS_ERR (d ))
@@ -123,6 +130,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
123130
124131err_out :
125132	inode_unlock (d_inode (parent_path -> dentry ));
133+ 	mnt_drop_write (parent_path -> mnt );
126134	path_put (parent_path );
127135	putname (filename );
128136	return  - ENOENT ;
@@ -451,7 +459,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
451459				 fp -> stream .name ,
452460				 (void  * )stream_buf ,
453461				 size ,
454- 				 0 );
462+ 				 0 ,
463+ 				 true);
455464	if  (err  <  0 )
456465		goto out ;
457466
@@ -593,10 +602,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
593602		goto out_err ;
594603	}
595604
596- 	err  =  mnt_want_write (path -> mnt );
597- 	if  (err )
598- 		goto out_err ;
599- 
600605	user_ns  =  mnt_user_ns (path -> mnt );
601606	if  (S_ISDIR (d_inode (path -> dentry )-> i_mode )) {
602607		err  =  vfs_rmdir (user_ns , d_inode (parent ), path -> dentry );
@@ -607,7 +612,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
607612		if  (err )
608613			ksmbd_debug (VFS , "unlink failed, err %d\n" , err );
609614	}
610- 	mnt_drop_write (path -> mnt );
611615
612616out_err :
613617	ksmbd_revert_fsids (work );
@@ -907,18 +911,22 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
907911 * @attr_value:	xattr value to set 
908912 * @attr_size:	size of xattr value 
909913 * @flags:	destination buffer length 
914+  * @get_write:	get write access to a mount 
910915 * 
911916 * Return:	0 on success, otherwise error 
912917 */ 
913918int  ksmbd_vfs_setxattr (struct  user_namespace  * user_ns ,
914919		       const  struct  path  * path , const  char  * attr_name ,
915- 		       const  void  * attr_value , size_t  attr_size , int  flags )
920+ 		       const  void  * attr_value , size_t  attr_size , int  flags ,
921+ 		       bool  get_write )
916922{
917923	int  err ;
918924
919- 	err  =  mnt_want_write (path -> mnt );
920- 	if  (err )
921- 		return  err ;
925+ 	if  (get_write  ==  true) {
926+ 		err  =  mnt_want_write (path -> mnt );
927+ 		if  (err )
928+ 			return  err ;
929+ 	}
922930
923931	err  =  vfs_setxattr (user_ns ,
924932			   path -> dentry ,
@@ -928,7 +936,8 @@ int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
928936			   flags );
929937	if  (err )
930938		ksmbd_debug (VFS , "setxattr failed, err %d\n" , err );
931- 	mnt_drop_write (path -> mnt );
939+ 	if  (get_write  ==  true)
940+ 		mnt_drop_write (path -> mnt );
932941	return  err ;
933942}
934943
@@ -1254,6 +1263,13 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
12541263	}
12551264
12561265	if  (!err ) {
1266+ 		err  =  mnt_want_write (parent_path -> mnt );
1267+ 		if  (err ) {
1268+ 			path_put (path );
1269+ 			path_put (parent_path );
1270+ 			return  err ;
1271+ 		}
1272+ 
12571273		err  =  ksmbd_vfs_lock_parent (parent_path -> dentry , path -> dentry );
12581274		if  (err ) {
12591275			path_put (path );
@@ -1263,6 +1279,14 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
12631279	return  err ;
12641280}
12651281
1282+ void  ksmbd_vfs_kern_path_unlock (struct  path  * parent_path , struct  path  * path )
1283+ {
1284+ 	inode_unlock (d_inode (parent_path -> dentry ));
1285+ 	mnt_drop_write (parent_path -> mnt );
1286+ 	path_put (path );
1287+ 	path_put (parent_path );
1288+ }
1289+ 
12661290struct  dentry  * ksmbd_vfs_kern_path_create (struct  ksmbd_work  * work ,
12671291					  const  char  * name ,
12681292					  unsigned int   flags ,
@@ -1412,7 +1436,8 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
14121436int  ksmbd_vfs_set_sd_xattr (struct  ksmbd_conn  * conn ,
14131437			   struct  user_namespace  * user_ns ,
14141438			   const  struct  path  * path ,
1415- 			   struct  smb_ntsd  * pntsd , int  len )
1439+ 			   struct  smb_ntsd  * pntsd , int  len ,
1440+ 			   bool  get_write )
14161441{
14171442	int  rc ;
14181443	struct  ndr  sd_ndr  =  {0 }, acl_ndr  =  {0 };
@@ -1472,7 +1497,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
14721497
14731498	rc  =  ksmbd_vfs_setxattr (user_ns , path ,
14741499				XATTR_NAME_SD , sd_ndr .data ,
1475- 				sd_ndr .offset , 0 );
1500+ 				sd_ndr .offset , 0 ,  get_write );
14761501	if  (rc  <  0 )
14771502		pr_err ("Failed to store XATTR ntacl :%d\n" , rc );
14781503
@@ -1561,7 +1586,8 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
15611586
15621587int  ksmbd_vfs_set_dos_attrib_xattr (struct  user_namespace  * user_ns ,
15631588				   const  struct  path  * path ,
1564- 				   struct  xattr_dos_attrib  * da )
1589+ 				   struct  xattr_dos_attrib  * da ,
1590+ 				   bool  get_write )
15651591{
15661592	struct  ndr  n ;
15671593	int  err ;
@@ -1571,7 +1597,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
15711597		return  err ;
15721598
15731599	err  =  ksmbd_vfs_setxattr (user_ns , path , XATTR_NAME_DOS_ATTRIBUTE ,
1574- 				 (void  * )n .data , n .offset , 0 );
1600+ 				 (void  * )n .data , n .offset , 0 ,  get_write );
15751601	if  (err )
15761602		ksmbd_debug (SMB , "failed to store dos attribute in xattr\n" );
15771603	kfree (n .data );
@@ -1841,10 +1867,6 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
18411867	}
18421868	posix_state_to_acl (& acl_state , acls -> a_entries );
18431869
1844- 	rc  =  mnt_want_write (path -> mnt );
1845- 	if  (rc )
1846- 		goto out_err ;
1847- 
18481870	rc  =  set_posix_acl (user_ns , inode , ACL_TYPE_ACCESS , acls );
18491871	if  (rc  <  0 )
18501872		ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n" ,
@@ -1857,9 +1879,7 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
18571879			ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n" ,
18581880				    rc );
18591881	}
1860- 	mnt_drop_write (path -> mnt );
18611882
1862- out_err :
18631883	free_acl_state (& acl_state );
18641884	posix_acl_release (acls );
18651885	return  rc ;
@@ -1888,10 +1908,6 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
18881908		}
18891909	}
18901910
1891- 	rc  =  mnt_want_write (path -> mnt );
1892- 	if  (rc )
1893- 		goto out_err ;
1894- 
18951911	rc  =  set_posix_acl (user_ns , inode , ACL_TYPE_ACCESS , acls );
18961912	if  (rc  <  0 )
18971913		ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n" ,
@@ -1903,9 +1919,7 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
19031919			ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n" ,
19041920				    rc );
19051921	}
1906- 	mnt_drop_write (path -> mnt );
19071922
1908- out_err :
19091923	posix_acl_release (acls );
19101924	return  rc ;
19111925}
0 commit comments