public inbox for linux-media@vger.kernel.org
 help / color / mirror / Atom feed
From: Michael Grzeschik <mgr@pengutronix.de>
To: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: linux-usb@vger.kernel.org, linux-media@vger.kernel.org,
	gregkh@linuxfoundation.org, balbi@kernel.org,
	kernel@pengutronix.de,
	Daniel Scally <dan.scally@ideasonboard.com>
Subject: Re: [PATCH v7] usb: gadget: uvc: add validate and fix function for uvc response
Date: Tue, 29 Nov 2022 11:23:08 +0100	[thread overview]
Message-ID: <20221129102308.GO18924@pengutronix.de> (raw)
In-Reply-To: <Y4V4IED+SBhUR7Su@pendragon.ideasonboard.com>

[-- Attachment #1: Type: text/plain, Size: 6264 bytes --]

On Tue, Nov 29, 2022 at 05:10:24AM +0200, Laurent Pinchart wrote:
>Hi Michael,
>
>(CC'ing Dan)
>
>Thank you for the patch.
>
>On Mon, Nov 28, 2022 at 11:31:25AM +0100, Michael Grzeschik wrote:
>> When the userspace gets the setup requests for UVC_GET_CUR UVC_GET_MIN,
>> UVC_GET_MAX, UVC_GET_DEF it will fill out the ctrl response. This data
>> needs to be validated. Since the kernel also knows the limits for valid
>> cases, it can fixup the values in case the userspace is setting invalid
>> data.
>
>Why is this a good idea ?

Why is it not? We don't want the userspace to communicate other things
to the host than what is configured in the configfs. If you only object
the explanation, then I will improve the commit message and send an
fixed v8. If you have more objections please share your doubts, thanks.

Michael

>> Fixes: e219a712bc06 ("usb: gadget: uvc: add v4l2 try_format api call")
>> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
>>
>> ---
>> v1: -> v4:
>> - new patch
>> v4: -> v5:
>> - changed uvcg_info to uvcg_dbg for fixups, updated info strings
>> v5: -> v6:
>> - no changes
>> v6 -> v7:
>> - reworked to not need 'd182bf156c4c ("usb: gadget: uvc: default the ctrl request interface offsets")'
>>
>> This will apply to v6.1-rc6.
>>
>>  drivers/usb/gadget/function/f_uvc.c    |  4 ++
>>  drivers/usb/gadget/function/uvc.h      |  1 +
>>  drivers/usb/gadget/function/uvc_v4l2.c | 76 ++++++++++++++++++++++++++
>>  3 files changed, 81 insertions(+)
>>
>> diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
>> index 6e196e06181ecf..89f0100dae60f4 100644
>> --- a/drivers/usb/gadget/function/f_uvc.c
>> +++ b/drivers/usb/gadget/function/f_uvc.c
>> @@ -248,6 +248,10 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>>  	memset(&v4l2_event, 0, sizeof(v4l2_event));
>>  	v4l2_event.type = UVC_EVENT_SETUP;
>>  	memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req));
>> +
>> +	if (interface == uvc->streaming_intf)
>> +		uvc->streaming_request = ctrl->bRequest;
>> +
>>  	v4l2_event_queue(&uvc->vdev, &v4l2_event);
>>
>>  	return 0;
>> diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
>> index 40226b1f7e148a..1be4d5f24b46bf 100644
>> --- a/drivers/usb/gadget/function/uvc.h
>> +++ b/drivers/usb/gadget/function/uvc.h
>> @@ -151,6 +151,7 @@ struct uvc_device {
>>  	void *control_buf;
>>
>>  	unsigned int streaming_intf;
>> +	unsigned char streaming_request;
>>
>>  	/* Events */
>>  	unsigned int event_length;
>> diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
>> index a189b08bba800d..a12475d289167a 100644
>> --- a/drivers/usb/gadget/function/uvc_v4l2.c
>> +++ b/drivers/usb/gadget/function/uvc_v4l2.c
>> @@ -178,6 +178,67 @@ static struct uvcg_frame *find_closest_frame_by_size(struct uvc_device *uvc,
>>   * Requests handling
>>   */
>>
>> +/* validate and fixup streaming ctrl request response data if possible */
>> +static void
>> +uvc_validate_streaming_ctrl(struct uvc_device *uvc,
>> +			    struct uvc_streaming_control *ctrl)
>> +{
>> +	struct f_uvc_opts *opts = fi_to_f_uvc_opts(uvc->func.fi);
>> +	unsigned int iformat, iframe;
>> +	struct uvcg_format *uformat;
>> +	struct uvcg_frame *uframe;
>> +	bool ival_found = false;
>> +	int i;
>> +
>> +	iformat = ctrl->bFormatIndex;
>> +	iframe = ctrl->bFrameIndex;
>> +
>> +	/* Restrict the iformat, iframe and dwFrameInterval to valid values.
>> +	 * Negative values for iformat and iframe will result in the maximum
>> +	 * valid value being selected
>> +	 */
>> +	iformat = clamp((unsigned int)iformat, 1U,
>> +			(unsigned int)uvc->header->num_fmt);
>> +	if (iformat != ctrl->bFormatIndex) {
>> +		uvcg_dbg(&uvc->func,
>> +			  "userspace set invalid format index - fixup\n");
>> +		ctrl->bFormatIndex = iformat;
>> +	}
>> +	uformat = find_format_by_index(uvc, iformat);
>> +
>> +	iframe = clamp((unsigned int)iframe, 1U,
>> +		       (unsigned int)uformat->num_frames);
>> +	if (iframe != ctrl->bFrameIndex) {
>> +		uvcg_dbg(&uvc->func,
>> +			  "userspace set invalid frame index - fixup\n");
>> +		ctrl->bFrameIndex = iframe;
>> +	}
>> +	uframe = find_frame_by_index(uvc, uformat, iframe);
>> +
>> +	if (ctrl->dwFrameInterval) {
>> +		for (i = 0; i < uframe->frame.b_frame_interval_type; i++) {
>> +			if (ctrl->dwFrameInterval ==
>> +				 uframe->dw_frame_interval[i])
>> +				ival_found = true;
>> +		}
>> +	}
>> +	if (!ival_found) {
>> +		uvcg_dbg(&uvc->func,
>> +			  "userspace set invalid frame interval - fixup\n");
>> +		ctrl->dwFrameInterval = uframe->frame.dw_default_frame_interval;
>> +	}
>> +
>> +	if (!ctrl->dwMaxPayloadTransferSize ||
>> +			ctrl->dwMaxPayloadTransferSize >
>> +				opts->streaming_maxpacket)
>> +		ctrl->dwMaxPayloadTransferSize = opts->streaming_maxpacket;
>> +
>> +	if (!ctrl->dwMaxVideoFrameSize ||
>> +			ctrl->dwMaxVideoFrameSize >
>> +				uframe->frame.dw_max_video_frame_buffer_size)
>> +		ctrl->dwMaxVideoFrameSize = uvc_get_frame_size(uformat, uframe);
>> +}
>> +
>>  static int
>>  uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
>>  {
>> @@ -192,6 +253,21 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
>>
>>  	memcpy(req->buf, data->data, req->length);
>>
>> +	/* validate the ctrl content and fixup */
>> +	if (!uvc->event_setup_out) {
>> +		struct uvc_streaming_control *ctrl = req->buf;
>> +
>> +		switch (uvc->streaming_request) {
>> +		case UVC_GET_CUR:
>> +		case UVC_GET_MIN:
>> +		case UVC_GET_MAX:
>> +		case UVC_GET_DEF:
>> +			uvc_validate_streaming_ctrl(uvc, ctrl);
>> +		default:
>> +			break;
>> +		}
>> +	}
>> +
>>  	return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
>>  }
>>
>
>-- 
>Regards,
>
>Laurent Pinchart
>

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2022-11-29 10:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-28 10:31 [PATCH v7] usb: gadget: uvc: add validate and fix function for uvc response Michael Grzeschik
2022-11-29  3:10 ` Laurent Pinchart
2022-11-29 10:23   ` Michael Grzeschik [this message]
2022-11-29 11:15     ` Dan Scally
2022-11-29 12:02     ` Laurent Pinchart
2022-11-29 15:22       ` Michael Grzeschik
2022-11-29 21:56         ` Michael Grzeschik
2022-12-03 21:29         ` Laurent Pinchart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221129102308.GO18924@pengutronix.de \
    --to=mgr@pengutronix.de \
    --cc=balbi@kernel.org \
    --cc=dan.scally@ideasonboard.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kernel@pengutronix.de \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox