@@ -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