lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 18 Mar 2021 10:09:42 +0100
From:   Hans Verkuil <hverkuil@...all.nl>
To:     Hans Verkuil <hverkuil-cisco@...all.nl>,
        Ricardo Ribalda <ribalda@...omium.org>,
        Laurent Pinchart <laurent.pinchart@...asonboard.com>,
        Mauro Carvalho Chehab <mchehab@...nel.org>,
        Sergey Senozhatsky <sergey.senozhatsky@...il.com>,
        linux-media@...r.kernel.org, linux-kernel@...r.kernel.org,
        tfiga@...omium.org
Subject: Re: [PATCH v6 16/17] media: uvcvideo: Return -EACCES to inactive
 controls

On 18/03/2021 08:39, Hans Verkuil wrote:
> Hi Ricardo,
> 
> On 17/03/2021 17:45, Ricardo Ribalda wrote:
>> If a control is inactive return -EACCES to let the userspace know that
>> the value will not be applied automatically when the control is active
>> again.

Note that this needs to be documented in vidioc-g-ext-ctrls.rst and
vidioc-g-ctrl.rst as well. Currently setting inactive controls shouldn't
return EACCES, but this has now changed.

Regards,

	Hans

>>
>> Signed-off-by: Ricardo Ribalda <ribalda@...omium.org>
>> Suggested-by: Hans Verkuil <hverkuil@...all.nl>
> 
> In several of the patches in this series you added 'Suggested-by' or 'Credit-to'.
> Please use <hverkuil-cisco@...all.nl> so Cisco gets the credit as well :-)
> 
>> ---
>>  drivers/media/usb/uvc/uvc_ctrl.c | 73 +++++++++++++++++++++++++-------
>>  drivers/media/usb/uvc/uvc_v4l2.c | 11 ++++-
>>  drivers/media/usb/uvc/uvcvideo.h |  3 +-
>>  3 files changed, 69 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
>> index af1d4d9b8afb..26d3494b401b 100644
>> --- a/drivers/media/usb/uvc/uvc_ctrl.c
>> +++ b/drivers/media/usb/uvc/uvc_ctrl.c
>> @@ -1046,10 +1046,62 @@ static int uvc_query_v4l2_class(struct uvc_video_chain *chain, u32 req_id,
>>  	return 0;
>>  }
>>  
>> -int uvc_ctrl_is_accesible(struct uvc_video_chain *chain, u32 v4l2_id, bool read)
>> +static bool uvc_ctrl_is_inactive(struct uvc_video_chain *chain,
>> +				 struct uvc_control *ctrl,
>> +				 struct uvc_control_mapping *mapping)
>> +{
>> +	struct uvc_control_mapping *master_map = NULL;
>> +	struct uvc_control *master_ctrl = NULL;
>> +	s32 val;
>> +	int ret;
>> +
>> +	if (!mapping->master_id)
>> +		return false;
>> +
>> +	__uvc_find_control(ctrl->entity, mapping->master_id, &master_map,
>> +			   &master_ctrl, 0);
>> +
>> +	if (!master_ctrl || !(master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
>> +		return false;
>> +
>> +	ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
>> +	if (ret < 0 || val == mapping->master_manual)
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>> +int uvc_ctrl_is_accesible(struct uvc_video_chain *chain, u32 v4l2_id,
> 
> Same typo: accesible -> accessible
> 
>> +			  unsigned long ioctl)
>>  {
>>  	struct uvc_control_mapping *mapping;
>>  	struct uvc_control *ctrl;
>> +	bool read, try;
>> +
>> +	switch (ioctl) {
>> +	case VIDIOC_G_EXT_CTRLS:
>> +		read = true;
>> +		try = false;
>> +		break;
>> +	case VIDIOC_S_EXT_CTRLS:
>> +		read = false;
>> +		try = false;
>> +		break;
>> +	case VIDIOC_TRY_EXT_CTRLS:
>> +		read = false;
>> +		try = true;
>> +		break;
>> +	case VIDIOC_G_CTRL:
>> +		read = true;
>> +		try = false;
>> +		break;
>> +	case VIDIOC_S_CTRL:
>> +		read = false;
>> +		try = false;
>> +		break;
>> +	default:
>> +		return -EINVAL;
>> +	}
> 
> That's ugly. Just remove the bools and switch and just check the ioctl below...
> 
>>  
>>  	if (__uvc_query_v4l2_class(chain, v4l2_id, 0) >= 0)
>>  		return -EACCES;
>> @@ -1064,6 +1116,9 @@ int uvc_ctrl_is_accesible(struct uvc_video_chain *chain, u32 v4l2_id, bool read)
>>  	if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) && !read)
>>  		return -EACCES;
>>  
>> +	if (!read && !try && uvc_ctrl_is_inactive(chain, ctrl, mapping))
> 
> and this becomes:
> 
> 	if ((ioctl == VIDIOC_S_EXT_CTRLS || ioctl == VIDIOC_S_CTRL) &&
> 	    uvc_ctrl_is_inactive(chain, ctrl, mapping))
> 
> Much, much simpler!
> 
>> +		return -EACCES;
>> +
>>  	return 0;
>>  }
>>  
>> @@ -1086,8 +1141,6 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
>>  	struct uvc_control_mapping *mapping,
>>  	struct v4l2_queryctrl *v4l2_ctrl)
>>  {
>> -	struct uvc_control_mapping *master_map = NULL;
>> -	struct uvc_control *master_ctrl = NULL;
>>  	const struct uvc_menu_info *menu;
>>  	unsigned int i;
>>  
>> @@ -1103,18 +1156,8 @@ static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
>>  	if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
>>  		v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>  
>> -	if (mapping->master_id)
>> -		__uvc_find_control(ctrl->entity, mapping->master_id,
>> -				   &master_map, &master_ctrl, 0);
>> -	if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
>> -		s32 val;
>> -		int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
>> -		if (ret < 0)
>> -			return ret;
>> -
>> -		if (val != mapping->master_manual)
>> -				v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
>> -	}
>> +	if (uvc_ctrl_is_inactive(chain, ctrl, mapping))
>> +		v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
>>  
>>  	if (!ctrl->cached) {
>>  		int ret = uvc_ctrl_populate_cache(chain, ctrl);
>> diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
>> index ce55b4bff687..8e9051a245c7 100644
>> --- a/drivers/media/usb/uvc/uvc_v4l2.c
>> +++ b/drivers/media/usb/uvc/uvc_v4l2.c
>> @@ -999,6 +999,10 @@ static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
>>  	struct v4l2_ext_control xctrl;
>>  	int ret;
>>  
>> +	ret = uvc_ctrl_is_accesible(chain, ctrl->id, VIDIOC_G_CTRL);
>> +	if (ret)
>> +		return ret;
>> +
>>  	memset(&xctrl, 0, sizeof(xctrl));
>>  	xctrl.id = ctrl->id;
>>  
>> @@ -1023,6 +1027,10 @@ static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
>>  	struct v4l2_ext_control xctrl;
>>  	int ret;
>>  
>> +	ret = uvc_ctrl_is_accesible(chain, ctrl->id, VIDIOC_S_CTRL);
>> +	if (ret)
>> +		return ret;
>> +
>>  	memset(&xctrl, 0, sizeof(xctrl));
>>  	xctrl.id = ctrl->id;
>>  	xctrl.value = ctrl->value;
>> @@ -1054,8 +1062,7 @@ static int uvc_ctrl_check_access(struct uvc_video_chain *chain,
>>  	int ret = 0;
>>  
>>  	for (i = 0; i < ctrls->count; ++ctrl, ++i) {
>> -		ret = uvc_ctrl_is_accesible(chain, ctrl->id,
>> -					    ioctl == VIDIOC_G_EXT_CTRLS);
>> +		ret = uvc_ctrl_is_accesible(chain, ctrl->id, ioctl);
>>  		if (ret)
>>  			break;
>>  	}
>> diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
>> index 3288b118264e..4e86d0983d58 100644
>> --- a/drivers/media/usb/uvc/uvcvideo.h
>> +++ b/drivers/media/usb/uvc/uvcvideo.h
>> @@ -902,7 +902,8 @@ static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
>>  
>>  int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl);
>>  int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl);
>> -int uvc_ctrl_is_accesible(struct uvc_video_chain *chain, u32 v4l2_id, bool read);
>> +int uvc_ctrl_is_accesible(struct uvc_video_chain *chain, u32 v4l2_id,
>> +			  unsigned long ioctl);
>>  
>>  int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
>>  		      struct uvc_xu_control_query *xqry);
>>
> 
> Regards,
> 
> 	Hans
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ