@@ -98,6 +98,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
9898 return - ENOENT ;
9999 }
100100
101+ err = mnt_want_write (parent_path -> mnt );
102+ if (err ) {
103+ path_put (parent_path );
104+ putname (filename );
105+ return - ENOENT ;
106+ }
107+
101108 inode_lock_nested (parent_path -> dentry -> d_inode , I_MUTEX_PARENT );
102109 d = lookup_one_qstr_excl (& last , parent_path -> dentry , 0 );
103110 if (IS_ERR (d ))
@@ -124,6 +131,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
124131
125132err_out :
126133 inode_unlock (d_inode (parent_path -> dentry ));
134+ mnt_drop_write (parent_path -> mnt );
127135 path_put (parent_path );
128136 putname (filename );
129137 return - ENOENT ;
@@ -452,7 +460,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
452460 fp -> stream .name ,
453461 (void * )stream_buf ,
454462 size ,
455- 0 );
463+ 0 ,
464+ true);
456465 if (err < 0 )
457466 goto out ;
458467
@@ -594,10 +603,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
594603 goto out_err ;
595604 }
596605
597- err = mnt_want_write (path -> mnt );
598- if (err )
599- goto out_err ;
600-
601606 user_ns = mnt_user_ns (path -> mnt );
602607 if (S_ISDIR (d_inode (path -> dentry )-> i_mode )) {
603608 err = vfs_rmdir (user_ns , d_inode (parent ), path -> dentry );
@@ -608,7 +613,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path)
608613 if (err )
609614 ksmbd_debug (VFS , "unlink failed, err %d\n" , err );
610615 }
611- mnt_drop_write (path -> mnt );
612616
613617out_err :
614618 ksmbd_revert_fsids (work );
@@ -908,18 +912,22 @@ ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
908912 * @attr_value: xattr value to set
909913 * @attr_size: size of xattr value
910914 * @flags: destination buffer length
915+ * @get_write: get write access to a mount
911916 *
912917 * Return: 0 on success, otherwise error
913918 */
914919int ksmbd_vfs_setxattr (struct user_namespace * user_ns ,
915920 const struct path * path , const char * attr_name ,
916- void * attr_value , size_t attr_size , int flags )
921+ void * attr_value , size_t attr_size , int flags ,
922+ bool get_write )
917923{
918924 int err ;
919925
920- err = mnt_want_write (path -> mnt );
921- if (err )
922- return err ;
926+ if (get_write == true) {
927+ err = mnt_want_write (path -> mnt );
928+ if (err )
929+ return err ;
930+ }
923931
924932 err = vfs_setxattr (user_ns ,
925933 path -> dentry ,
@@ -929,7 +937,8 @@ int ksmbd_vfs_setxattr(struct user_namespace *user_ns,
929937 flags );
930938 if (err )
931939 ksmbd_debug (VFS , "setxattr failed, err %d\n" , err );
932- mnt_drop_write (path -> mnt );
940+ if (get_write == true)
941+ mnt_drop_write (path -> mnt );
933942 return err ;
934943}
935944
@@ -1253,6 +1262,13 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
12531262 }
12541263
12551264 if (!err ) {
1265+ err = mnt_want_write (parent_path -> mnt );
1266+ if (err ) {
1267+ path_put (path );
1268+ path_put (parent_path );
1269+ return err ;
1270+ }
1271+
12561272 err = ksmbd_vfs_lock_parent (parent_path -> dentry , path -> dentry );
12571273 if (err ) {
12581274 path_put (path );
@@ -1262,6 +1278,14 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
12621278 return err ;
12631279}
12641280
1281+ void ksmbd_vfs_kern_path_unlock (struct path * parent_path , struct path * path )
1282+ {
1283+ inode_unlock (d_inode (parent_path -> dentry ));
1284+ mnt_drop_write (parent_path -> mnt );
1285+ path_put (path );
1286+ path_put (parent_path );
1287+ }
1288+
12651289struct dentry * ksmbd_vfs_kern_path_create (struct ksmbd_work * work ,
12661290 const char * name ,
12671291 unsigned int flags ,
@@ -1411,7 +1435,8 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
14111435int ksmbd_vfs_set_sd_xattr (struct ksmbd_conn * conn ,
14121436 struct user_namespace * user_ns ,
14131437 const struct path * path ,
1414- struct smb_ntsd * pntsd , int len )
1438+ struct smb_ntsd * pntsd , int len ,
1439+ bool get_write )
14151440{
14161441 int rc ;
14171442 struct ndr sd_ndr = {0 }, acl_ndr = {0 };
@@ -1471,7 +1496,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn,
14711496
14721497 rc = ksmbd_vfs_setxattr (user_ns , path ,
14731498 XATTR_NAME_SD , sd_ndr .data ,
1474- sd_ndr .offset , 0 );
1499+ sd_ndr .offset , 0 , get_write );
14751500 if (rc < 0 )
14761501 pr_err ("Failed to store XATTR ntacl :%d\n" , rc );
14771502
@@ -1560,7 +1585,8 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
15601585
15611586int ksmbd_vfs_set_dos_attrib_xattr (struct user_namespace * user_ns ,
15621587 const struct path * path ,
1563- struct xattr_dos_attrib * da )
1588+ struct xattr_dos_attrib * da ,
1589+ bool get_write )
15641590{
15651591 struct ndr n ;
15661592 int err ;
@@ -1570,7 +1596,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns,
15701596 return err ;
15711597
15721598 err = ksmbd_vfs_setxattr (user_ns , path , XATTR_NAME_DOS_ATTRIBUTE ,
1573- (void * )n .data , n .offset , 0 );
1599+ (void * )n .data , n .offset , 0 , get_write );
15741600 if (err )
15751601 ksmbd_debug (SMB , "failed to store dos attribute in xattr\n" );
15761602 kfree (n .data );
@@ -1840,10 +1866,6 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
18401866 }
18411867 posix_state_to_acl (& acl_state , acls -> a_entries );
18421868
1843- rc = mnt_want_write (path -> mnt );
1844- if (rc )
1845- goto out_err ;
1846-
18471869 rc = set_posix_acl (user_ns , inode , ACL_TYPE_ACCESS , acls );
18481870 if (rc < 0 )
18491871 ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n" ,
@@ -1856,9 +1878,7 @@ int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
18561878 ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n" ,
18571879 rc );
18581880 }
1859- mnt_drop_write (path -> mnt );
18601881
1861- out_err :
18621882 free_acl_state (& acl_state );
18631883 posix_acl_release (acls );
18641884 return rc ;
@@ -1887,10 +1907,6 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
18871907 }
18881908 }
18891909
1890- rc = mnt_want_write (path -> mnt );
1891- if (rc )
1892- goto out_err ;
1893-
18941910 rc = set_posix_acl (user_ns , inode , ACL_TYPE_ACCESS , acls );
18951911 if (rc < 0 )
18961912 ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n" ,
@@ -1902,9 +1918,7 @@ int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
19021918 ksmbd_debug (SMB , "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n" ,
19031919 rc );
19041920 }
1905- mnt_drop_write (path -> mnt );
19061921
1907- out_err :
19081922 posix_acl_release (acls );
19091923 return rc ;
19101924}
0 commit comments