Re: [PATCH] ksmbd: smbd: validate buffer descriptor structures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
>
>



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux