All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] [media] dvb_demux: fix deadlock in dmx_section_feed_release_filter()
@ 2013-08-17 20:48 Alexey Khoroshilov
  2013-09-26 17:08 ` Mauro Carvalho Chehab
  0 siblings, 1 reply; 3+ messages in thread
From: Alexey Khoroshilov @ 2013-08-17 20:48 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Alexey Khoroshilov, linux-media, linux-kernel, ldv-project

dmx_section_feed_release_filter() locks dvbdmx->mutex and
if the feed is still filtering, it calls feed->stop_filtering(feed).
stop_filtering() is implemented by dmx_section_feed_stop_filtering()
that first of all try to lock the same mutex: dvbdmx->mutex.
That leads to a deadlock.

It does not happen often in practice because all callers of
release_filter() stop filtering by themselves.
So the problem can happen in case of race condition only.

The patch proposes to unlock dvbdmx->mutex before call feed->stop_filtering(feed)
and recheck feed->is_filtering after reacquiring mutex.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
 drivers/media/dvb-core/dvb_demux.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index 3485655..9d517af 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -1027,8 +1027,11 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
 		return -EINVAL;
 	}
 
-	if (feed->is_filtering)
+	while (feed->is_filtering) {
+		mutex_unlock(&dvbdmx->mutex);
 		feed->stop_filtering(feed);
+		mutex_lock(&dvbdmx->mutex);
+	}
 
 	spin_lock_irq(&dvbdmx->lock);
 	f = dvbdmxfeed->filter;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] [media] dvb_demux: fix deadlock in dmx_section_feed_release_filter()
  2013-08-17 20:48 [PATCH] [media] dvb_demux: fix deadlock in dmx_section_feed_release_filter() Alexey Khoroshilov
@ 2013-09-26 17:08 ` Mauro Carvalho Chehab
  2013-10-07 21:04   ` [PATCH v2] " Alexey Khoroshilov
  0 siblings, 1 reply; 3+ messages in thread
From: Mauro Carvalho Chehab @ 2013-09-26 17:08 UTC (permalink / raw)
  To: Alexey Khoroshilov; +Cc: linux-media, linux-kernel, ldv-project

Em Sat, 17 Aug 2013 23:48:51 +0300
Alexey Khoroshilov <khoroshilov@ispras.ru> escreveu:

> dmx_section_feed_release_filter() locks dvbdmx->mutex and
> if the feed is still filtering, it calls feed->stop_filtering(feed).
> stop_filtering() is implemented by dmx_section_feed_stop_filtering()
> that first of all try to lock the same mutex: dvbdmx->mutex.
> That leads to a deadlock.
> 
> It does not happen often in practice because all callers of
> release_filter() stop filtering by themselves.
> So the problem can happen in case of race condition only.
> 
> The patch proposes to unlock dvbdmx->mutex before call feed->stop_filtering(feed)
> and recheck feed->is_filtering after reacquiring mutex.
> 
> Found by Linux Driver Verification project (linuxtesting.org).
> 
> Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
> ---
>  drivers/media/dvb-core/dvb_demux.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
> index 3485655..9d517af 100644
> --- a/drivers/media/dvb-core/dvb_demux.c
> +++ b/drivers/media/dvb-core/dvb_demux.c
> @@ -1027,8 +1027,11 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
>  		return -EINVAL;
>  	}
>  
> -	if (feed->is_filtering)
> +	while (feed->is_filtering) {

Changing from if to while here can cause a dead lock, as, if the device
got removed, dmx_section_feed_stop_filtering() won't touch
feed->is_filtering. So, the loop will happen forever.

Except for that the patch looks correct on my eyes.

> +		mutex_unlock(&dvbdmx->mutex);

Please add a small comment about why the mutex needs to be unlocked
there, as this looks ugly, and likely deserve some cleanups in the future
(as both the spinclock and the mutex are taken on both callback and at
the release filter function).

>  		feed->stop_filtering(feed);
> +		mutex_lock(&dvbdmx->mutex);
> +	}
>  
>  	spin_lock_irq(&dvbdmx->lock);
>  	f = dvbdmxfeed->filter;


Thanks!
Mauro

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2] [media] dvb_demux: fix deadlock in dmx_section_feed_release_filter()
  2013-09-26 17:08 ` Mauro Carvalho Chehab
@ 2013-10-07 21:04   ` Alexey Khoroshilov
  0 siblings, 0 replies; 3+ messages in thread
From: Alexey Khoroshilov @ 2013-10-07 21:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Alexey Khoroshilov, linux-media, linux-kernel, ldv-project

dmx_section_feed_release_filter() locks dvbdmx->mutex and
if the feed is still filtering, it calls feed->stop_filtering(feed).
stop_filtering() is implemented by dmx_section_feed_stop_filtering()
that first of all try to lock the same mutex: dvbdmx->mutex.
That leads to a deadlock.

It does not happen often in practice because all callers of
release_filter() stop filtering by themselves.
So the problem can happen in case of race condition only.

The patch releases dvbdmx->mutex before call to feed->stop_filtering(feed)
and reacquires the mutex after that.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
---
 drivers/media/dvb-core/dvb_demux.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index 3485655..6de3bd0 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -1027,8 +1027,13 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
 		return -EINVAL;
 	}
 
-	if (feed->is_filtering)
+	if (feed->is_filtering) {
+		/* release dvbdmx->mutex as far as 
+		   it is acquired by stop_filtering() itself */
+		mutex_unlock(&dvbdmx->mutex);
 		feed->stop_filtering(feed);
+		mutex_lock(&dvbdmx->mutex);
+	}
 
 	spin_lock_irq(&dvbdmx->lock);
 	f = dvbdmxfeed->filter;
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-10-07 21:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-17 20:48 [PATCH] [media] dvb_demux: fix deadlock in dmx_section_feed_release_filter() Alexey Khoroshilov
2013-09-26 17:08 ` Mauro Carvalho Chehab
2013-10-07 21:04   ` [PATCH v2] " Alexey Khoroshilov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.