mirror of
https://github.com/torvalds/linux.git
synced 2026-10-08 11:36:02 +02:00
ksmbd: report actual xattr value length for stream EndOfFile/AllocationSize
fp->stream.size holds the byte length of the mangled xattr *name* string (it's used as the attr_name_len argument when looking up the xattr), not the size of the stream's actual data. CREATE and every QUERY_INFO handler that reports EndOfFile/AllocationSize for a stream handle used fp->stream.size directly, so clients received a bogus size derived from the internal xattr key name length instead of the stream's real content length. Add ksmbd_stream_eof() to query the xattr's actual value length via ksmbd_vfs_casexattr_len(), and use it at every site that reports a stream handle's size: the CREATE response, get_file_standard_info(), get_file_all_info(), get_file_network_open_info(), and find_file_posix_info(). Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
495ade881b
commit
a9417bb188
|
|
@ -2822,6 +2822,22 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fp->stream.size is the byte length of the mangled xattr *name*
|
||||
* (used as attr_name_len when looking the xattr up), not the size of
|
||||
* the xattr's value. Reporting it as EndOfFile/AllocationSize for a
|
||||
* stream handle is wrong -- query the xattr's actual value length
|
||||
* instead.
|
||||
*/
|
||||
static loff_t ksmbd_stream_eof(struct ksmbd_file *fp)
|
||||
{
|
||||
ssize_t slen = ksmbd_vfs_casexattr_len(file_mnt_idmap(fp->filp),
|
||||
fp->filp->f_path.dentry,
|
||||
fp->stream.name,
|
||||
fp->stream.size);
|
||||
return slen < 0 ? 0 : (loff_t)slen;
|
||||
}
|
||||
|
||||
static int smb2_remove_smb_xattrs(const struct path *path)
|
||||
{
|
||||
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
|
||||
|
|
@ -4106,10 +4122,17 @@ int smb2_open(struct ksmbd_work *work)
|
|||
* using the raw on-disk block count, which can include filesystem
|
||||
* preallocation and metadata rounding.
|
||||
*/
|
||||
if (!S_ISDIR(stat.mode) && stat.size > fp->allocation_size)
|
||||
fp->allocation_size = round_up(stat.size, stat.blksize);
|
||||
rsp->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
if (ksmbd_stream_fd(fp)) {
|
||||
loff_t seof = ksmbd_stream_eof(fp);
|
||||
|
||||
rsp->AllocationSize = cpu_to_le64((u64)seof);
|
||||
rsp->EndofFile = cpu_to_le64((u64)seof);
|
||||
} else {
|
||||
if (!S_ISDIR(stat.mode) && stat.size > fp->allocation_size)
|
||||
fp->allocation_size = round_up(stat.size, stat.blksize);
|
||||
rsp->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
}
|
||||
rsp->FileAttributes = fp->f_ci->m_fattr;
|
||||
|
||||
rsp->Reserved2 = 0;
|
||||
|
|
@ -5450,8 +5473,10 @@ static int get_file_standard_info(struct smb2_query_info_rsp *rsp,
|
|||
sinfo->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
} else {
|
||||
sinfo->AllocationSize = cpu_to_le64(fp->stream.size);
|
||||
sinfo->EndOfFile = cpu_to_le64(fp->stream.size);
|
||||
loff_t seof = ksmbd_stream_eof(fp);
|
||||
|
||||
sinfo->AllocationSize = cpu_to_le64((u64)seof);
|
||||
sinfo->EndOfFile = cpu_to_le64((u64)seof);
|
||||
}
|
||||
sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
|
||||
sinfo->DeletePending = delete_pending;
|
||||
|
|
@ -5529,8 +5554,10 @@ static int get_file_all_info(struct ksmbd_work *work,
|
|||
file_info->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
} else {
|
||||
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
|
||||
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
|
||||
loff_t seof = ksmbd_stream_eof(fp);
|
||||
|
||||
file_info->AllocationSize = cpu_to_le64((u64)seof);
|
||||
file_info->EndOfFile = cpu_to_le64((u64)seof);
|
||||
}
|
||||
file_info->NumberOfLinks =
|
||||
cpu_to_le32(get_nlink(&stat) - delete_pending);
|
||||
|
|
@ -5807,8 +5834,10 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
|
|||
file_info->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
} else {
|
||||
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
|
||||
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
|
||||
loff_t seof = ksmbd_stream_eof(fp);
|
||||
|
||||
file_info->AllocationSize = cpu_to_le64((u64)seof);
|
||||
file_info->EndOfFile = cpu_to_le64((u64)seof);
|
||||
}
|
||||
file_info->Reserved = cpu_to_le32(0);
|
||||
rsp->OutputBufferLength =
|
||||
|
|
@ -5939,8 +5968,10 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
|
|||
file_info->EndOfFile = cpu_to_le64(stat.size);
|
||||
file_info->AllocationSize = cpu_to_le64(fp->allocation_size);
|
||||
} else {
|
||||
file_info->EndOfFile = cpu_to_le64(fp->stream.size);
|
||||
file_info->AllocationSize = cpu_to_le64(fp->stream.size);
|
||||
loff_t seof = ksmbd_stream_eof(fp);
|
||||
|
||||
file_info->EndOfFile = cpu_to_le64((u64)seof);
|
||||
file_info->AllocationSize = cpu_to_le64((u64)seof);
|
||||
}
|
||||
file_info->HardLinks = cpu_to_le32(stat.nlink);
|
||||
file_info->Mode = cpu_to_le32(stat.mode & 0777);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user