Unverified Commit 07c809cf authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!15649 media: uvcvideo: Remove dangling pointers

parents 5acc828b fc4c24c3
Loading
Loading
Loading
Loading
+62 −2
Original line number Diff line number Diff line
@@ -1276,6 +1276,40 @@ static void uvc_ctrl_send_slave_event(struct uvc_video_chain *chain,
	uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes);
}

static void uvc_ctrl_set_handle(struct uvc_fh *handle, struct uvc_control *ctrl,
				struct uvc_fh *new_handle)
{
	lockdep_assert_held(&handle->chain->ctrl_mutex);

	if (new_handle) {
		if (ctrl->handle)
			dev_warn_ratelimited(&handle->stream->dev->udev->dev,
					     "UVC non compliance: Setting an async control with a pending operation.");

		if (new_handle == ctrl->handle)
			return;

		if (ctrl->handle) {
			WARN_ON(!ctrl->handle->pending_async_ctrls);
			if (ctrl->handle->pending_async_ctrls)
				ctrl->handle->pending_async_ctrls--;
		}

		ctrl->handle = new_handle;
		handle->pending_async_ctrls++;
		return;
	}

	/* Cannot clear the handle for a control not owned by us.*/
	if (WARN_ON(ctrl->handle != handle))
		return;

	ctrl->handle = NULL;
	if (WARN_ON(!handle->pending_async_ctrls))
		return;
	handle->pending_async_ctrls--;
}

static void uvc_ctrl_status_event_work(struct work_struct *work)
{
	struct uvc_device *dev = container_of(work, struct uvc_device,
@@ -1291,7 +1325,8 @@ static void uvc_ctrl_status_event_work(struct work_struct *work)
	mutex_lock(&chain->ctrl_mutex);

	handle = ctrl->handle;
	ctrl->handle = NULL;
	if (handle)
		uvc_ctrl_set_handle(handle, ctrl, NULL);

	list_for_each_entry(mapping, &ctrl->info.mappings, list) {
		s32 value = __uvc_ctrl_get_value(mapping, w->data);
@@ -1684,7 +1719,7 @@ int uvc_ctrl_set(struct uvc_fh *handle,
		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));

	if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
		ctrl->handle = handle;
		uvc_ctrl_set_handle(handle, ctrl, handle);

	ctrl->dirty = 1;
	ctrl->modified = 1;
@@ -2330,6 +2365,31 @@ int uvc_ctrl_init_device(struct uvc_device *dev)
	return 0;
}

void uvc_ctrl_cleanup_fh(struct uvc_fh *handle)
{
	struct uvc_entity *entity;

	mutex_lock(&handle->chain->ctrl_mutex);

	if (!handle->pending_async_ctrls) {
		mutex_unlock(&handle->chain->ctrl_mutex);
		return;
	}

	list_for_each_entry(entity, &handle->chain->dev->entities, list) {
		unsigned int i;

		for (i = 0; i < entity->ncontrols; ++i) {
			if (entity->controls[i].handle != handle)
				continue;
			uvc_ctrl_set_handle(handle, &entity->controls[i], NULL);
		}
	}

	WARN_ON(handle->pending_async_ctrls);
	mutex_unlock(&handle->chain->ctrl_mutex);
}

/*
 * Cleanup device controls.
 */
+2 −0
Original line number Diff line number Diff line
@@ -563,6 +563,8 @@ static int uvc_v4l2_release(struct file *file)

	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");

	uvc_ctrl_cleanup_fh(handle);

	/* Only free resources if this is a privileged handle. */
	if (uvc_has_privileges(handle))
		uvc_queue_release(&stream->queue);
+8 −1
Original line number Diff line number Diff line
@@ -434,7 +434,11 @@ struct uvc_video_chain {
	struct uvc_entity *processing;		/* Processing unit */
	struct uvc_entity *selector;		/* Selector unit */

	struct mutex ctrl_mutex;		/* Protects ctrl.info */
	struct mutex ctrl_mutex;		/*
						 * Protects ctrl.info,
						 * ctrl.handle and
						 * uvc_fh.pending_async_ctrls
						 */

	struct v4l2_prio_state prio;		/* V4L2 priority state */
	u32 caps;				/* V4L2 chain-wide caps */
@@ -626,6 +630,7 @@ struct uvc_fh {
	struct uvc_video_chain *chain;
	struct uvc_streaming *stream;
	enum uvc_handle_state state;
	unsigned int pending_async_ctrls;
};

struct uvc_driver {
@@ -792,6 +797,8 @@ int uvc_ctrl_set(struct uvc_fh *handle, struct v4l2_ext_control *xctrl);
int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
		      struct uvc_xu_control_query *xqry);

void uvc_ctrl_cleanup_fh(struct uvc_fh *handle);

/* Utility functions */
void uvc_simplify_fraction(u32 *numerator, u32 *denominator,
			   unsigned int n_terms, unsigned int threshold);