mirror of
https://github.com/torvalds/linux.git
synced 2024-11-12 23:23:03 +00:00
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. Cc: stable@vger.kernel.org Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
e8f897f4af
commit
5614c8c487
@ -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 @@ out:
|
||||
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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user