v4l: event: Add subscription to list before calling "add" operation
Subsystems (2)
PATCH 1/1 v4l: event: Add subscription to list before calling "add" operation
[ upstream commit 92539d3eda2c090b382699bbb896d4b54e9bdece ]
Patch ad608fbcf166 changed how events were subscribed to address an issue elsewhere. As a side effect of that change, the "add" callback was called before the event subscription was added to the list of subscribed events, causing the first event queued by the add callback (and possibly other events arriving soon afterwards) to be lost.
Fix this by adding the subscription to the list before calling the "add" callback, and clean up afterwards if that fails.
---
Hi Greg,
This is a backport of a fix in the media tree for the 4.9 stable series.
<URL:https://git.linuxtv.org/media_tree.git/commit/?id=92539d3eda2c090b382699bbb896d4b54e9bdece>
I'll send patches for 4.4 and 3.16 (to Ben H.) kernels shortly.
drivers/media/v4l2-core/v4l2-event.c | 43 ++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-)
drivers/media/v4l2-core/v4l2-event.c +24 -19
@@ -197,6 +197,22 @@ int v4l2_event_pending(struct v4l2_fh *fh) }EXPORT_SYMBOL_GPL (v4l2_event_pending); +static void __v4l2_event_unsubscribe (struct v4l2_subscribed_event *sev) +{ +struct v4l2_fh *fh = sev->fh; +unsigned int i; + +lockdep_assert_held (&fh->subscribe_lock); +assert_spin_locked (&fh->vdev->fh_lock); + +/* Remove any pending events for this subscription */ +for (i =0 ; i < sev->in_use; i++) { +list_del (&sev->events[sev_pos (sev, i)].list); + fh->navailable--; + } +list_del (&sev->list); +} +int v4l2_event_subscribe (struct v4l2_fh *fh,const struct v4l2_event_subscription *sub,unsigned elems,const struct v4l2_subscribed_event_ops *ops)
@@ -228,27 +244,23 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,spin_lock_irqsave (&fh->vdev->fh_lock, flags); found_ev =v4l2_event_subscribed (fh, sub->type, sub->id); +if (!found_ev) +list_add (&sev->list, &fh->subscribed);spin_unlock_irqrestore (&fh->vdev->fh_lock, flags);if (found_ev) {/* Already listening */ kfree (sev); - goto out_unlock; - } - -if (sev->ops && sev->ops->add) { + }else if (sev->ops && sev->ops->add) { ret = sev->ops->add (sev, elems);if (ret) { +spin_lock_irqsave (&fh->vdev->fh_lock, flags); +__v4l2_event_unsubscribe (sev); +spin_unlock_irqrestore (&fh->vdev->fh_lock, flags);kfree (sev); - goto out_unlock; } } -spin_lock_irqsave (&fh->vdev->fh_lock, flags); -list_add (&sev->list, &fh->subscribed); -spin_unlock_irqrestore (&fh->vdev->fh_lock, flags); - -out_unlock:mutex_unlock (&fh->subscribe_lock);return ret;
@@ -283,7 +295,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, {struct v4l2_subscribed_event *sev;unsigned long flags; -int i;if (sub->type ==V4L2_EVENT_ALL ) {v4l2_event_unsubscribe_all (fh);
@@ -295,14 +306,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,spin_lock_irqsave (&fh->vdev->fh_lock, flags); sev =v4l2_event_subscribed (fh, sub->type, sub->id); -if (sev !=NULL ) { -/* Remove any pending events for this subscription */ -for (i =0 ; i < sev->in_use; i++) { -list_del (&sev->events[sev_pos (sev, i)].list); - fh->navailable--; - } -list_del (&sev->list); - } +if (sev !=NULL ) +__v4l2_event_unsubscribe (sev);spin_unlock_irqrestore (&fh->vdev->fh_lock, flags);
Signature · 1 line
2.11.0
Sasha Levin
maintainerQuoted 13 lines · Sakari Ailus
[ upstream commit
92539d3eda2c090b382699bbb896d4b54e9bdece]Patch
ad608fbcf166changed how events were subscribed to address an issue elsewhere. As a side effect of that change, the "add" callback was called before the event subscription was added to the list of subscribed events, causing the first event queued by the add callback (and possibly other events arriving soon afterwards) to be lost.Fix this by adding the subscription to the list before calling the "add" callback, and clean up afterwards if that fails.
Fixes ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions while accessed")
Quoted 7 lines
Reported-by Dave Stevenson <[email protected]>Signed-off-by Sakari Ailus <[email protected]>Tested-by Dave Stevenson <[email protected]>Reviewed-by Hans Verkuil <[email protected]>Tested-by Hans Verkuil <[email protected]>Cc [email protected] (for 4.14 and up)Signed-off-by Mauro Carvalho Chehab <[email protected]>
Hi Sakari,
For the sake of completeness, can you sign off on the backport too and indicate it was backported to 4.9 in the commit messge? Otherwise, this commit message says it's for 4.14+ and will suddenly appear in the 4.9 tree, and if we have issues later it might cause confusion.
--
Thanks,
Sasha
Hi Sasha,
Quoted 22 lines · Sasha Levin
Quoted 13 lines · Sakari Ailus
[ upstream commit
92539d3eda2c090b382699bbb896d4b54e9bdece]Patch
ad608fbcf166changed how events were subscribed to address an issue elsewhere. As a side effect of that change, the "add" callback was called before the event subscription was added to the list of subscribed events, causing the first event queued by the add callback (and possibly other events arriving soon afterwards) to be lost.Fix this by adding the subscription to the list before calling the "add" callback, and clean up afterwards if that fails.
Fixes ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions while accessed")Quoted 7 lines
Reported-by Dave Stevenson <[email protected]>Signed-off-by Sakari Ailus <[email protected]>Tested-by Dave Stevenson <[email protected]>Reviewed-by Hans Verkuil <[email protected]>Tested-by Hans Verkuil <[email protected]>Cc [email protected] (for 4.14 and up)Signed-off-by Mauro Carvalho Chehab <[email protected]>
Quoted 6 lines
Hi Sakari,
For the sake of completeness, can you sign off on the backport too and indicate it was backported to 4.9 in the commit messge? Otherwise, this commit message says it's for 4.14+ and will suddenly appear in the 4.9 tree, and if we have issues later it might cause confusion.
Yes; I'll fix the above issues and resend.
Thanks!
Signature · 2 lines
Sakari Ailus [email protected]