Re: [PATCH v4.9 1/1] v4l: event: Add subscription to list before calling "add" operation

2018-11-14 Thread Sakari Ailus
Hi Sasha,

On Thu, Nov 08, 2018 at 12:28:53PM -0500, Sasha Levin wrote:
> On Thu, Nov 08, 2018 at 01:46:06PM +0200, Sakari Ailus wrote:
> > [ 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.
> > 
> > Fixes: ad608fbcf166 ("media: v4l: event: Prevent freeing event 
> > subscriptions while accessed")
> > 
> > Reported-by: Dave Stevenson 
> > Signed-off-by: Sakari Ailus 
> > Tested-by: Dave Stevenson 
> > Reviewed-by: Hans Verkuil 
> > Tested-by: Hans Verkuil 
> > Cc: sta...@vger.kernel.org (for 4.14 and up)
> > Signed-off-by: Mauro Carvalho Chehab 
> 
> 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!

-- 
Sakari Ailus
sakari.ai...@linux.intel.com


Re: [PATCH v4.9 1/1] v4l: event: Add subscription to list before calling "add" operation

2018-11-08 Thread Sasha Levin

On Thu, Nov 08, 2018 at 01:46:06PM +0200, Sakari Ailus wrote:

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

Fixes: ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions while 
accessed")

Reported-by: Dave Stevenson 
Signed-off-by: Sakari Ailus 
Tested-by: Dave Stevenson 
Reviewed-by: Hans Verkuil 
Tested-by: Hans Verkuil 
Cc: sta...@vger.kernel.org (for 4.14 and up)
Signed-off-by: Mauro Carvalho Chehab 


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


[PATCH v4.9 1/1] v4l: event: Add subscription to list before calling "add" operation

2018-11-08 Thread Sakari Ailus
[ 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.

Fixes: ad608fbcf166 ("media: v4l: event: Prevent freeing event subscriptions 
while accessed")

Reported-by: Dave Stevenson 
Signed-off-by: Sakari Ailus 
Tested-by: Dave Stevenson 
Reviewed-by: Hans Verkuil 
Tested-by: Hans Verkuil 
Cc: sta...@vger.kernel.org (for 4.14 and up)
Signed-off-by: Mauro Carvalho Chehab 
---
Hi Greg,

This is a backport of a fix in the media tree for the 4.9 stable series.

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

diff --git a/drivers/media/v4l2-core/v4l2-event.c 
b/drivers/media/v4l2-core/v4l2-event.c
index 567d86835f001..1fda2873375f6 100644
--- a/drivers/media/v4l2-core/v4l2-event.c
+++ b/drivers/media/v4l2-core/v4l2-event.c
@@ -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(>subscribe_lock);
+   assert_spin_locked(>vdev->fh_lock);
+
+   /* Remove any pending events for this subscription */
+   for (i = 0; i < sev->in_use; i++) {
+   list_del(>events[sev_pos(sev, i)].list);
+   fh->navailable--;
+   }
+   list_del(>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(>vdev->fh_lock, flags);
found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
+   if (!found_ev)
+   list_add(>list, >subscribed);
spin_unlock_irqrestore(>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(>vdev->fh_lock, flags);
+   __v4l2_event_unsubscribe(sev);
+   spin_unlock_irqrestore(>vdev->fh_lock, flags);
kfree(sev);
-   goto out_unlock;
}
}
 
-   spin_lock_irqsave(>vdev->fh_lock, flags);
-   list_add(>list, >subscribed);
-   spin_unlock_irqrestore(>vdev->fh_lock, flags);
-
-out_unlock:
mutex_unlock(>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(>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(>events[sev_pos(sev, i)].list);
-   fh->navailable--;
-   }
-   list_del(>list);
-   }
+   if (sev != NULL)
+   __v4l2_event_unsubscribe(sev);
 
spin_unlock_irqrestore(>vdev->fh_lock, flags);
 
-- 
2.11.0