2022-01-20 0:01 GMT+09:00, Hyunchul Lee <hyc.lee@xxxxxxxxx>: > Check ChannelInfoOffset and ChannelInfoLength > to validate buffer descriptor structures. > And add a debug log to print the structures' > content. > > Signed-off-by: Hyunchul Lee <hyc.lee@xxxxxxxxx> > --- > fs/ksmbd/smb2pdu.c | 31 +++++++++++++++++++++++++------ > 1 file changed, 25 insertions(+), 6 deletions(-) > > diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c > index c3f248d461e6..f664fbadb09a 100644 > --- a/fs/ksmbd/smb2pdu.c > +++ b/fs/ksmbd/smb2pdu.c > @@ -6130,12 +6130,20 @@ static int smb2_set_remote_key_for_rdma(struct > ksmbd_work *work, > __le16 ChannelInfoOffset, > __le16 ChannelInfoLength) > { > + unsigned int i, ch_count; > + > if (work->conn->dialect == SMB30_PROT_ID && > Channel != SMB2_CHANNEL_RDMA_V1) > return -EINVAL; > > - if (ChannelInfoOffset == 0 || > - le16_to_cpu(ChannelInfoLength) < sizeof(*desc)) > + ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc); > + for (i = 0; i < ch_count; i++) { unneeded loop is executed on non-debug mode. I think that this loop is covered with rdma debug. Please check this : if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) { } > + ksmbd_debug(RDMA, "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) Need to add error print that ksmbd doesn't support multiple buffer desc yet. > return -EINVAL; And multiple buffer desc support is required for a fundamental solution, but it is expected that it will take a very long time for you to implement it. Is that right? If so, first, find a way to set the optimal read/write size so that the client send a single buffer desc to ksmbd. > > work->need_invalidate_rkey = > @@ -6189,9 +6197,15 @@ int smb2_read(struct ksmbd_work *work) > > if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || > 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, > (struct smb2_buffer_desc_v1 *) > - &req->Buffer[0], > + ((char *)req + ch_offset), > req->Channel, > req->ReadChannelInfoOffset, > req->ReadChannelInfoLength); > @@ -6432,11 +6446,16 @@ int smb2_write(struct ksmbd_work *work) > > if (req->Channel == SMB2_CHANNEL_RDMA_V1 || > req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { > - if (req->Length != 0 || req->DataOffset != 0) > - return -EINVAL; > + unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset); > + > + 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, > (struct smb2_buffer_desc_v1 *) > - &req->Buffer[0], > + ((char *)req + ch_offset), > req->Channel, > req->WriteChannelInfoOffset, > req->WriteChannelInfoLength); > -- > 2.25.1 > >