FAILED: Patch "ksmbd: replace generic_fillattr with vfs_getattr" failed to apply to 5.4-stable tree
Subsystems (3)
Sasha Levin
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 5614c8c487f6af627614dd2efca038e4afe0c6d7 Mon Sep 17 00:00:00 2001
From: Marios Makassikis <[email protected]>
Date: Thu, 22 Feb 2024 10:58:19 +0100
Subject: [PATCH] ksmbd: replace generic_fillattr with vfs_getattr
generic_fillattr should not be used outside of ->getattr implementations.
Use vfs_getattr instead, and adapt functions to return an error code to the caller.
Signed-off-by Marios Makassikis <[email protected]>
Acked-by Namjae Jeon <[email protected]>
Signed-off-by Steve French <[email protected]>
--- fs/smb/server/smb2pdu.c | 170 ++++++++++++++++++++++++------------- fs/smb/server/smb_common.c | 11 ++- fs/smb/server/vfs.c | 12 ++- 3 files changed, 127 insertions(+), 66 deletions(-)
fs/smb/server/smb2pdu.c +110 -60
@@ -3828,11 +3828,16 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv) } ksmbd_kstat.kstat = &kstat; -if (priv->info_level !=FILE_NAMES_INFORMATION ) -ksmbd_vfs_fill_dentry_attrs (priv->work, - idmap, - dent, - &ksmbd_kstat); +if (priv->info_level !=FILE_NAMES_INFORMATION ) { + rc =ksmbd_vfs_fill_dentry_attrs (priv->work, + idmap, + dent, + &ksmbd_kstat); +if (rc) { +dput (dent); +continue ; + } + } rc = smb2_populate_readdir_entry(priv->work->conn, priv->info_level,
@@ -4480,6 +4485,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,struct smb2_file_basic_info *basic_info;struct kstat stat;u64 time; +int ret;if (!(fp->daccess &FILE_READ_ATTRIBUTES_LE )) { pr_err("no right to read the attributes : 0x%x\n",
@@ -4487,9 +4493,12 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,return -EACCES ; } + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; + basic_info = (struct smb2_file_basic_info *)rsp->Buffer; -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , -file_inode (fp->filp), &stat); basic_info->CreationTime =cpu_to_le64 (fp->create_time); time =ksmbd_UnixTimeToNT (stat.atime); basic_info->LastAccessTime =cpu_to_le64 (time);
@@ -4504,27 +4513,31 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,return 0 ; } -static void get_file_standard_info (struct smb2_query_info_rsp *rsp, -struct ksmbd_file *fp,void *rsp_org) +static int get_file_standard_info (struct smb2_query_info_rsp *rsp, +struct ksmbd_file *fp,void *rsp_org) {struct smb2_file_standard_info *sinfo;unsigned int delete_pending; -struct inode *inode;struct kstat stat; +int ret; - inode =file_inode (fp->filp); -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , inode, &stat); + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; sinfo = (struct smb2_file_standard_info *)rsp->Buffer; delete_pending =ksmbd_inode_pending_delete (fp); - sinfo->AllocationSize =cpu_to_le64 (inode->i_blocks <<9 ); + sinfo->AllocationSize =cpu_to_le64 (stat.blocks <<9 ); sinfo->EndOfFile =S_ISDIR (stat.mode) ?0 :cpu_to_le64 (stat.size); sinfo->NumberOfLinks =cpu_to_le32 (get_nlink (&stat) - delete_pending); sinfo->DeletePending = delete_pending; sinfo->Directory =S_ISDIR (stat.mode) ?1 :0 ; rsp->OutputBufferLength =cpu_to_le32 (sizeof (struct smb2_file_standard_info )); + +return 0 ; } static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
@@ -4546,11 +4559,11 @@ static int get_file_all_info(struct ksmbd_work *work,struct ksmbd_conn *conn = work->conn;struct smb2_file_all_info *file_info;unsigned int delete_pending; -struct inode *inode;struct kstat stat;int conv_len;char *filename;u64 time; +int ret;if (!(fp->daccess &FILE_READ_ATTRIBUTES_LE )) { ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
@@ -4562,8 +4575,10 @@ static int get_file_all_info(struct ksmbd_work *work,if (IS_ERR (filename))return PTR_ERR (filename); - inode =file_inode (fp->filp); -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , inode, &stat); + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret;ksmbd_debug (SMB ,"filename = %s\n" , filename); delete_pending =ksmbd_inode_pending_delete (fp);
@@ -4579,7 +4594,7 @@ static int get_file_all_info(struct ksmbd_work *work, file_info->Attributes = fp->f_ci->m_fattr; file_info->Pad1 =0 ; file_info->AllocationSize = -cpu_to_le64 (inode->i_blocks <<9 ); +cpu_to_le64 (stat.blocks <<9 ); file_info->EndOfFile =S_ISDIR (stat.mode) ?0 :cpu_to_le64 (stat.size); file_info->NumberOfLinks =cpu_to_le32 (get_nlink (&stat) - delete_pending);
@@ -4623,10 +4638,10 @@ static void get_file_alternate_info(struct ksmbd_work *work,cpu_to_le32 (sizeof (struct smb2_file_alt_name_info ) + conv_len); } -static void get_file_stream_info (struct ksmbd_work *work, -struct smb2_query_info_rsp *rsp, -struct ksmbd_file *fp, -void *rsp_org) +static int get_file_stream_info (struct ksmbd_work *work, +struct smb2_query_info_rsp *rsp, +struct ksmbd_file *fp, +void *rsp_org) {struct ksmbd_conn *conn = work->conn;struct smb2_file_stream_info *file_info;
@@ -4637,9 +4652,13 @@ static void get_file_stream_info(struct ksmbd_work *work,int nbytes =0 , streamlen, stream_name_len, next, idx =0 ;int buf_free_len;struct smb2_query_info_req *req =ksmbd_req_buf_next (work); +int ret; + + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , -file_inode (fp->filp), &stat); file_info = (struct smb2_file_stream_info *)rsp->Buffer; buf_free_len =
@@ -4720,29 +4739,37 @@ static void get_file_stream_info(struct ksmbd_work *work,kvfree (xattr_list); rsp->OutputBufferLength =cpu_to_le32 (nbytes); + +return 0 ; } -static void get_file_internal_info (struct smb2_query_info_rsp *rsp, -struct ksmbd_file *fp,void *rsp_org) +static int get_file_internal_info (struct smb2_query_info_rsp *rsp, +struct ksmbd_file *fp,void *rsp_org) {struct smb2_file_internal_info *file_info;struct kstat stat; +int ret; + + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , -file_inode (fp->filp), &stat); file_info = (struct smb2_file_internal_info *)rsp->Buffer; file_info->IndexNumber =cpu_to_le64 (stat.ino); rsp->OutputBufferLength =cpu_to_le32 (sizeof (struct smb2_file_internal_info )); + +return 0 ; }static int get_file_network_open_info (struct smb2_query_info_rsp *rsp,struct ksmbd_file *fp,void *rsp_org) {struct smb2_file_ntwrk_info *file_info; -struct inode *inode;struct kstat stat;u64 time; +int ret;if (!(fp->daccess &FILE_READ_ATTRIBUTES_LE )) { pr_err("no right to read the attributes : 0x%x\n",
@@ -4750,10 +4777,12 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,return -EACCES ; } - file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; - inode =file_inode (fp->filp); -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , inode, &stat); + file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; file_info->CreationTime =cpu_to_le64 (fp->create_time); time =ksmbd_UnixTimeToNT (stat.atime);
@@ -4763,8 +4792,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp, time =ksmbd_UnixTimeToNT (stat.ctime); file_info->ChangeTime =cpu_to_le64 (time); file_info->Attributes = fp->f_ci->m_fattr; - file_info->AllocationSize = -cpu_to_le64 (inode->i_blocks <<9 ); + file_info->AllocationSize =cpu_to_le64 (stat.blocks <<9 ); file_info->EndOfFile =S_ISDIR (stat.mode) ?0 :cpu_to_le64 (stat.size); file_info->Reserved =cpu_to_le32 (0 ); rsp->OutputBufferLength =
@@ -4804,14 +4832,17 @@ static void get_file_mode_info(struct smb2_query_info_rsp *rsp,cpu_to_le32 (sizeof (struct smb2_file_mode_info )); } -static void get_file_compression_info (struct smb2_query_info_rsp *rsp, -struct ksmbd_file *fp,void *rsp_org) +static int get_file_compression_info (struct smb2_query_info_rsp *rsp, +struct ksmbd_file *fp,void *rsp_org) {struct smb2_file_comp_info *file_info;struct kstat stat; +int ret; -generic_fillattr (file_mnt_idmap (fp->filp),STATX_BASIC_STATS , -file_inode (fp->filp), &stat); + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; file_info = (struct smb2_file_comp_info *)rsp->Buffer; file_info->CompressedFileSize =cpu_to_le64 (stat.blocks <<9 );
@@ -4823,6 +4854,8 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp, rsp->OutputBufferLength =cpu_to_le32 (sizeof (struct smb2_file_comp_info )); + +return 0 ; } static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
@@ -4844,7 +4877,7 @@ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,return 0 ; } -static void find_file_posix_info (struct smb2_query_info_rsp *rsp, +static int find_file_posix_info (struct smb2_query_info_rsp *rsp,struct ksmbd_file *fp,void *rsp_org) {struct smb311_posix_qinfo *file_info;
@@ -4852,24 +4885,31 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp,struct mnt_idmap *idmap =file_mnt_idmap (fp->filp);vfsuid_t vfsuid =i_uid_into_vfsuid (idmap, inode);vfsgid_t vfsgid =i_gid_into_vfsgid (idmap, inode); +struct kstat stat;u64 time;int out_buf_len =sizeof (struct smb311_posix_qinfo ) +32 ; +int ret; + + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) +return ret; file_info = (struct smb311_posix_qinfo *)rsp->Buffer; file_info->CreationTime =cpu_to_le64 (fp->create_time); - time =ksmbd_UnixTimeToNT (inode_get_atime (inode)); + time =ksmbd_UnixTimeToNT (stat.atime); file_info->LastAccessTime =cpu_to_le64 (time); - time =ksmbd_UnixTimeToNT (inode_get_mtime (inode)); + time =ksmbd_UnixTimeToNT (stat.mtime); file_info->LastWriteTime =cpu_to_le64 (time); - time =ksmbd_UnixTimeToNT (inode_get_ctime (inode)); + time =ksmbd_UnixTimeToNT (stat.ctime); file_info->ChangeTime =cpu_to_le64 (time); file_info->DosAttributes = fp->f_ci->m_fattr; - file_info->Inode =cpu_to_le64 (inode->i_ino); - file_info->EndOfFile =cpu_to_le64 (inode->i_size); - file_info->AllocationSize =cpu_to_le64 (inode->i_blocks <<9 ); - file_info->HardLinks =cpu_to_le32 (inode->i_nlink); - file_info->Mode =cpu_to_le32 (inode->i_mode &0777 ); - file_info->DeviceId =cpu_to_le32 (inode->i_rdev); + file_info->Inode =cpu_to_le64 (stat.ino); + file_info->EndOfFile =cpu_to_le64 (stat.size); + file_info->AllocationSize =cpu_to_le64 (stat.blocks <<9 ); + file_info->HardLinks =cpu_to_le32 (stat.nlink); + file_info->Mode =cpu_to_le32 (stat.mode &0777 ); + file_info->DeviceId =cpu_to_le32 (stat.rdev);/* * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
@@ -4882,6 +4922,8 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp, SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]); rsp->OutputBufferLength =cpu_to_le32 (out_buf_len); + +return 0 ; } static int smb2_get_info_file(struct ksmbd_work *work,
@@ -4930,7 +4972,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,break ;case FILE_STANDARD_INFORMATION : -get_file_standard_info (rsp, fp, work->response_buf); + rc =get_file_standard_info (rsp, fp, work->response_buf);break ;case FILE_ALIGNMENT_INFORMATION :
@@ -4946,11 +4988,11 @@ static int smb2_get_info_file(struct ksmbd_work *work,break ;case FILE_STREAM_INFORMATION : -get_file_stream_info (work, rsp, fp, work->response_buf); + rc =get_file_stream_info (work, rsp, fp, work->response_buf);break ;case FILE_INTERNAL_INFORMATION : -get_file_internal_info (rsp, fp, work->response_buf); + rc =get_file_internal_info (rsp, fp, work->response_buf);break ;case FILE_NETWORK_OPEN_INFORMATION :
@@ -4974,7 +5016,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,break ;case FILE_COMPRESSION_INFORMATION : -get_file_compression_info (rsp, fp, work->response_buf); + rc =get_file_compression_info (rsp, fp, work->response_buf);break ;case FILE_ATTRIBUTE_TAG_INFORMATION :
@@ -4985,7 +5027,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,pr_err ("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n" ); rc = -EOPNOTSUPP ; }else { -find_file_posix_info (rsp, fp, work->response_buf); + rc =find_file_posix_info (rsp, fp, work->response_buf); }break ;default :
@@ -5398,7 +5440,6 @@ int smb2_close(struct ksmbd_work *work)struct smb2_close_rsp *rsp;struct ksmbd_conn *conn = work->conn;struct ksmbd_file *fp; -struct inode *inode;u64 time;int err =0 ;
@@ -5453,24 +5494,33 @@ int smb2_close(struct ksmbd_work *work) rsp->Reserved =0 ;if (req->Flags ==SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB ) { +struct kstat stat; +int ret; + fp =ksmbd_lookup_fd_fast (work, volatile_id);if (!fp) { err = -ENOENT ; goto out; } - inode =file_inode (fp->filp); + ret =vfs_getattr (&fp->filp->f_path, &stat,STATX_BASIC_STATS , +AT_STATX_SYNC_AS_STAT ); +if (ret) { +ksmbd_fd_put (work, fp); + goto out; + } + rsp->Flags =SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB ; - rsp->AllocationSize =S_ISDIR (inode->i_mode) ?0 : -cpu_to_le64 (inode->i_blocks <<9 ); - rsp->EndOfFile =cpu_to_le64 (inode->i_size); + rsp->AllocationSize =S_ISDIR (stat.mode) ?0 : +cpu_to_le64 (stat.blocks <<9 ); + rsp->EndOfFile =cpu_to_le64 (stat.size); rsp->Attributes = fp->f_ci->m_fattr; rsp->CreationTime =cpu_to_le64 (fp->create_time); - time =ksmbd_UnixTimeToNT (inode_get_atime (inode)); + time =ksmbd_UnixTimeToNT (stat.atime); rsp->LastAccessTime =cpu_to_le64 (time); - time =ksmbd_UnixTimeToNT (inode_get_mtime (inode)); + time =ksmbd_UnixTimeToNT (stat.mtime); rsp->LastWriteTime =cpu_to_le64 (time); - time =ksmbd_UnixTimeToNT (inode_get_ctime (inode)); + time =ksmbd_UnixTimeToNT (stat.ctime); rsp->ChangeTime =cpu_to_le64 (time);ksmbd_fd_put (work, fp); }else {
fs/smb/server/smb_common.c +7 -4
@@ -457,10 +457,13 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, } ksmbd_kstat.kstat = &kstat; -ksmbd_vfs_fill_dentry_attrs (work, - idmap, - dentry, - &ksmbd_kstat); + rc =ksmbd_vfs_fill_dentry_attrs (work, + idmap, + dentry, + &ksmbd_kstat); +if (rc) +break ; + rc =fn (conn, info_level, d_info, &ksmbd_kstat);if (rc)break ;
fs/smb/server/vfs.c +10 -2
@@ -1682,11 +1682,19 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,struct dentry *dentry, struct ksmbd_kstat *ksmbd_kstat) { + struct ksmbd_share_config *share_conf = work->tcon->share_conf;u64 time;int rc; +struct path path = { + .mnt = share_conf->vfs_path.mnt, + .dentry = dentry, + }; -generic_fillattr (idmap,STATX_BASIC_STATS ,d_inode (dentry), - ksmbd_kstat->kstat); + rc =vfs_getattr (&path, ksmbd_kstat->kstat, +STATX_BASIC_STATS |STATX_BTIME , +AT_STATX_SYNC_AS_STAT ); +if (rc) +return rc; time =ksmbd_UnixTimeToNT (ksmbd_kstat->kstat->ctime); ksmbd_kstat->create_time = time;
Signature · 1 line
2.43.0