Commit c2788502 authored by Simon Arlott's avatar Simon Arlott Committed by Mauro Carvalho Chehab

V4L/DVB (5400): Core: fix several locking related problems

Fix several instances of dvb-core functions using mutex_lock_interruptible
and returning -ERESTARTSYS where the calling function will either never
retry or never check the return value.
These cause a race condition with dvb_dmxdev_filter_free and
dvb_dvr_release, both of which are filesystem release functions whose
return value is ignored and will never be retried.  When this happens it
becomes impossible to open dvr0 again (-EBUSY) since it has not been
released properly.
Signed-off-by: default avatarSimon Arlott <simon@fire.lp0.eu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Acked-By: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent b10fece5
...@@ -180,8 +180,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) ...@@ -180,8 +180,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv; struct dmxdev *dmxdev = dvbdev->priv;
if (mutex_lock_interruptible(&dmxdev->mutex)) mutex_lock(&dmxdev->mutex);
return -ERESTARTSYS;
if ((file->f_flags & O_ACCMODE) == O_WRONLY) { if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
dmxdev->demux->disconnect_frontend(dmxdev->demux); dmxdev->demux->disconnect_frontend(dmxdev->demux);
...@@ -673,13 +672,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file) ...@@ -673,13 +672,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter) struct dmxdev_filter *dmxdevfilter)
{ {
if (mutex_lock_interruptible(&dmxdev->mutex)) mutex_lock(&dmxdev->mutex);
return -ERESTARTSYS; mutex_lock(&dmxdevfilter->mutex);
if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
mutex_unlock(&dmxdev->mutex);
return -ERESTARTSYS;
}
dvb_dmxdev_filter_stop(dmxdevfilter); dvb_dmxdev_filter_stop(dmxdevfilter);
dvb_dmxdev_filter_reset(dmxdevfilter); dvb_dmxdev_filter_reset(dmxdevfilter);
......
...@@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed) ...@@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
struct dvb_demux *demux = feed->demux; struct dvb_demux *demux = feed->demux;
int ret; int ret;
if (mutex_lock_interruptible(&demux->mutex)) mutex_lock(&demux->mutex);
return -ERESTARTSYS;
if (feed->state < DMX_STATE_GO) { if (feed->state < DMX_STATE_GO) {
mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex);
...@@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, ...@@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
struct dvb_demux *demux = (struct dvb_demux *)dmx; struct dvb_demux *demux = (struct dvb_demux *)dmx;
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
if (mutex_lock_interruptible(&demux->mutex)) mutex_lock(&demux->mutex);
return -ERESTARTSYS;
if (feed->state == DMX_STATE_FREE) { if (feed->state == DMX_STATE_FREE) {
mutex_unlock(&demux->mutex); mutex_unlock(&demux->mutex);
...@@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed) ...@@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
int ret; int ret;
if (mutex_lock_interruptible(&dvbdmx->mutex)) mutex_lock(&dvbdmx->mutex);
return -ERESTARTSYS;
if (!dvbdmx->stop_feed) { if (!dvbdmx->stop_feed) {
mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex);
...@@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, ...@@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
if (mutex_lock_interruptible(&dvbdmx->mutex)) mutex_lock(&dvbdmx->mutex);
return -ERESTARTSYS;
if (dvbdmxfilter->feed != dvbdmxfeed) { if (dvbdmxfilter->feed != dvbdmxfeed) {
mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex);
...@@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux, ...@@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
if (mutex_lock_interruptible(&dvbdmx->mutex)) mutex_lock(&dvbdmx->mutex);
return -ERESTARTSYS;
if (dvbdmxfeed->state == DMX_STATE_FREE) { if (dvbdmxfeed->state == DMX_STATE_FREE) {
mutex_unlock(&dvbdmx->mutex); mutex_unlock(&dvbdmx->mutex);
...@@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux, ...@@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux,
if (demux->frontend) if (demux->frontend)
return -EINVAL; return -EINVAL;
if (mutex_lock_interruptible(&dvbdemux->mutex)) mutex_lock(&dvbdemux->mutex);
return -ERESTARTSYS;
demux->frontend = frontend; demux->frontend = frontend;
mutex_unlock(&dvbdemux->mutex); mutex_unlock(&dvbdemux->mutex);
...@@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux) ...@@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
{ {
struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
if (mutex_lock_interruptible(&dvbdemux->mutex)) mutex_lock(&dvbdemux->mutex);
return -ERESTARTSYS;
demux->frontend = NULL; demux->frontend = NULL;
mutex_unlock(&dvbdemux->mutex); mutex_unlock(&dvbdemux->mutex);
......
...@@ -203,8 +203,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, ...@@ -203,8 +203,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
int id; int id;
if (mutex_lock_interruptible(&dvbdev_register_lock)) mutex_lock(&dvbdev_register_lock);
return -ERESTARTSYS;
if ((id = dvbdev_get_free_id (adap, type)) < 0){ if ((id = dvbdev_get_free_id (adap, type)) < 0){
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
...@@ -294,8 +293,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu ...@@ -294,8 +293,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
{ {
int num; int num;
if (mutex_lock_interruptible(&dvbdev_register_lock)) mutex_lock(&dvbdev_register_lock);
return -ERESTARTSYS;
if ((num = dvbdev_get_free_adapter_num ()) < 0) { if ((num = dvbdev_get_free_adapter_num ()) < 0) {
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
...@@ -323,8 +321,7 @@ EXPORT_SYMBOL(dvb_register_adapter); ...@@ -323,8 +321,7 @@ EXPORT_SYMBOL(dvb_register_adapter);
int dvb_unregister_adapter(struct dvb_adapter *adap) int dvb_unregister_adapter(struct dvb_adapter *adap)
{ {
if (mutex_lock_interruptible(&dvbdev_register_lock)) mutex_lock(&dvbdev_register_lock);
return -ERESTARTSYS;
list_del (&adap->list_head); list_del (&adap->list_head);
mutex_unlock(&dvbdev_register_lock); mutex_unlock(&dvbdev_register_lock);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment