ksmbd: smbd: validate buffer descriptor structures
Check ChannelInfoOffset and ChannelInfoLength to validate buffer descriptor structures. And add a debug log to print the structures' content. Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
9ca8581e79
commit
6d896d3b44
|
@ -6126,13 +6126,26 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
|
||||||
__le16 ChannelInfoOffset,
|
__le16 ChannelInfoOffset,
|
||||||
__le16 ChannelInfoLength)
|
__le16 ChannelInfoLength)
|
||||||
{
|
{
|
||||||
|
unsigned int i, ch_count;
|
||||||
|
|
||||||
if (work->conn->dialect == SMB30_PROT_ID &&
|
if (work->conn->dialect == SMB30_PROT_ID &&
|
||||||
Channel != SMB2_CHANNEL_RDMA_V1)
|
Channel != SMB2_CHANNEL_RDMA_V1)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ChannelInfoOffset == 0 ||
|
ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
|
||||||
le16_to_cpu(ChannelInfoLength) < sizeof(*desc))
|
if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
|
||||||
|
for (i = 0; i < ch_count; i++) {
|
||||||
|
pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
|
||||||
|
i,
|
||||||
|
le32_to_cpu(desc[i].token),
|
||||||
|
le32_to_cpu(desc[i].length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch_count != 1) {
|
||||||
|
ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
|
||||||
|
ch_count);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
work->need_invalidate_rkey =
|
work->need_invalidate_rkey =
|
||||||
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
|
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
|
||||||
|
@ -6185,9 +6198,15 @@ int smb2_read(struct ksmbd_work *work)
|
||||||
|
|
||||||
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
|
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
|
||||||
req->Channel == SMB2_CHANNEL_RDMA_V1) {
|
req->Channel == SMB2_CHANNEL_RDMA_V1) {
|
||||||
|
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
|
||||||
|
|
||||||
|
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
err = smb2_set_remote_key_for_rdma(work,
|
err = smb2_set_remote_key_for_rdma(work,
|
||||||
(struct smb2_buffer_desc_v1 *)
|
(struct smb2_buffer_desc_v1 *)
|
||||||
&req->Buffer[0],
|
((char *)req + ch_offset),
|
||||||
req->Channel,
|
req->Channel,
|
||||||
req->ReadChannelInfoOffset,
|
req->ReadChannelInfoOffset,
|
||||||
req->ReadChannelInfoLength);
|
req->ReadChannelInfoLength);
|
||||||
|
@ -6428,11 +6447,16 @@ int smb2_write(struct ksmbd_work *work)
|
||||||
|
|
||||||
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
|
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
|
||||||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
|
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
|
||||||
if (req->Length != 0 || req->DataOffset != 0)
|
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
|
||||||
return -EINVAL;
|
|
||||||
|
if (req->Length != 0 || req->DataOffset != 0 ||
|
||||||
|
ch_offset < offsetof(struct smb2_write_req, Buffer)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
err = smb2_set_remote_key_for_rdma(work,
|
err = smb2_set_remote_key_for_rdma(work,
|
||||||
(struct smb2_buffer_desc_v1 *)
|
(struct smb2_buffer_desc_v1 *)
|
||||||
&req->Buffer[0],
|
((char *)req + ch_offset),
|
||||||
req->Channel,
|
req->Channel,
|
||||||
req->WriteChannelInfoOffset,
|
req->WriteChannelInfoOffset,
|
||||||
req->WriteChannelInfoLength);
|
req->WriteChannelInfoLength);
|
||||||
|
|
Loading…
Reference in New Issue