aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Arlott <simon@fire.lp0.eu>2007-03-10 04:21:25 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-03-27 07:45:54 -0400
commitc278850206fd9df0bb62a72ca0b277fe20c5a452 (patch)
tree439ae68737b5bcb5d473b3d12c3d5417f697ccb3
parentb10fece583fdfdb3d2f29b0da3896ec58b8fe122 (diff)
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: Simon Arlott <simon@fire.lp0.eu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-By: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c21
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c9
3 files changed, 13 insertions, 29 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index fc77de45ca4d..a5c0e1a3e6d1 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -180,8 +180,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
180 struct dvb_device *dvbdev = file->private_data; 180 struct dvb_device *dvbdev = file->private_data;
181 struct dmxdev *dmxdev = dvbdev->priv; 181 struct dmxdev *dmxdev = dvbdev->priv;
182 182
183 if (mutex_lock_interruptible(&dmxdev->mutex)) 183 mutex_lock(&dmxdev->mutex);
184 return -ERESTARTSYS;
185 184
186 if ((file->f_flags & O_ACCMODE) == O_WRONLY) { 185 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
187 dmxdev->demux->disconnect_frontend(dmxdev->demux); 186 dmxdev->demux->disconnect_frontend(dmxdev->demux);
@@ -673,13 +672,8 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
673static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, 672static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
674 struct dmxdev_filter *dmxdevfilter) 673 struct dmxdev_filter *dmxdevfilter)
675{ 674{
676 if (mutex_lock_interruptible(&dmxdev->mutex)) 675 mutex_lock(&dmxdev->mutex);
677 return -ERESTARTSYS; 676 mutex_lock(&dmxdevfilter->mutex);
678
679 if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
680 mutex_unlock(&dmxdev->mutex);
681 return -ERESTARTSYS;
682 }
683 677
684 dvb_dmxdev_filter_stop(dmxdevfilter); 678 dvb_dmxdev_filter_stop(dmxdevfilter);
685 dvb_dmxdev_filter_reset(dmxdevfilter); 679 dvb_dmxdev_filter_reset(dmxdevfilter);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index fcff5eab21a3..6d8d1c3df863 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -673,8 +673,7 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
673 struct dvb_demux *demux = feed->demux; 673 struct dvb_demux *demux = feed->demux;
674 int ret; 674 int ret;
675 675
676 if (mutex_lock_interruptible(&demux->mutex)) 676 mutex_lock(&demux->mutex);
677 return -ERESTARTSYS;
678 677
679 if (feed->state < DMX_STATE_GO) { 678 if (feed->state < DMX_STATE_GO) {
680 mutex_unlock(&demux->mutex); 679 mutex_unlock(&demux->mutex);
@@ -748,8 +747,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
748 struct dvb_demux *demux = (struct dvb_demux *)dmx; 747 struct dvb_demux *demux = (struct dvb_demux *)dmx;
749 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed; 748 struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
750 749
751 if (mutex_lock_interruptible(&demux->mutex)) 750 mutex_lock(&demux->mutex);
752 return -ERESTARTSYS;
753 751
754 if (feed->state == DMX_STATE_FREE) { 752 if (feed->state == DMX_STATE_FREE) {
755 mutex_unlock(&demux->mutex); 753 mutex_unlock(&demux->mutex);
@@ -916,8 +914,7 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
916 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 914 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
917 int ret; 915 int ret;
918 916
919 if (mutex_lock_interruptible(&dvbdmx->mutex)) 917 mutex_lock(&dvbdmx->mutex);
920 return -ERESTARTSYS;
921 918
922 if (!dvbdmx->stop_feed) { 919 if (!dvbdmx->stop_feed) {
923 mutex_unlock(&dvbdmx->mutex); 920 mutex_unlock(&dvbdmx->mutex);
@@ -942,8 +939,7 @@ static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
942 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 939 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
943 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 940 struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
944 941
945 if (mutex_lock_interruptible(&dvbdmx->mutex)) 942 mutex_lock(&dvbdmx->mutex);
946 return -ERESTARTSYS;
947 943
948 if (dvbdmxfilter->feed != dvbdmxfeed) { 944 if (dvbdmxfilter->feed != dvbdmxfeed) {
949 mutex_unlock(&dvbdmx->mutex); 945 mutex_unlock(&dvbdmx->mutex);
@@ -1016,8 +1012,7 @@ static int dvbdmx_release_section_feed(struct dmx_demux *demux,
1016 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed; 1012 struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
1017 struct dvb_demux *dvbdmx = (struct dvb_demux *)demux; 1013 struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
1018 1014
1019 if (mutex_lock_interruptible(&dvbdmx->mutex)) 1015 mutex_lock(&dvbdmx->mutex);
1020 return -ERESTARTSYS;
1021 1016
1022 if (dvbdmxfeed->state == DMX_STATE_FREE) { 1017 if (dvbdmxfeed->state == DMX_STATE_FREE) {
1023 mutex_unlock(&dvbdmx->mutex); 1018 mutex_unlock(&dvbdmx->mutex);
@@ -1126,8 +1121,7 @@ static int dvbdmx_connect_frontend(struct dmx_demux *demux,
1126 if (demux->frontend) 1121 if (demux->frontend)
1127 return -EINVAL; 1122 return -EINVAL;
1128 1123
1129 if (mutex_lock_interruptible(&dvbdemux->mutex)) 1124 mutex_lock(&dvbdemux->mutex);
1130 return -ERESTARTSYS;
1131 1125
1132 demux->frontend = frontend; 1126 demux->frontend = frontend;
1133 mutex_unlock(&dvbdemux->mutex); 1127 mutex_unlock(&dvbdemux->mutex);
@@ -1138,8 +1132,7 @@ static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
1138{ 1132{
1139 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1133 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1140 1134
1141 if (mutex_lock_interruptible(&dvbdemux->mutex)) 1135 mutex_lock(&dvbdemux->mutex);
1142 return -ERESTARTSYS;
1143 1136
1144 demux->frontend = NULL; 1137 demux->frontend = NULL;
1145 mutex_unlock(&dvbdemux->mutex); 1138 mutex_unlock(&dvbdemux->mutex);
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 490337b5ee3e..14a372a0fe8b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -203,8 +203,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
203 203
204 int id; 204 int id;
205 205
206 if (mutex_lock_interruptible(&dvbdev_register_lock)) 206 mutex_lock(&dvbdev_register_lock);
207 return -ERESTARTSYS;
208 207
209 if ((id = dvbdev_get_free_id (adap, type)) < 0){ 208 if ((id = dvbdev_get_free_id (adap, type)) < 0){
210 mutex_unlock(&dvbdev_register_lock); 209 mutex_unlock(&dvbdev_register_lock);
@@ -294,8 +293,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
294{ 293{
295 int num; 294 int num;
296 295
297 if (mutex_lock_interruptible(&dvbdev_register_lock)) 296 mutex_lock(&dvbdev_register_lock);
298 return -ERESTARTSYS;
299 297
300 if ((num = dvbdev_get_free_adapter_num ()) < 0) { 298 if ((num = dvbdev_get_free_adapter_num ()) < 0) {
301 mutex_unlock(&dvbdev_register_lock); 299 mutex_unlock(&dvbdev_register_lock);
@@ -323,8 +321,7 @@ EXPORT_SYMBOL(dvb_register_adapter);
323 321
324int dvb_unregister_adapter(struct dvb_adapter *adap) 322int dvb_unregister_adapter(struct dvb_adapter *adap)
325{ 323{
326 if (mutex_lock_interruptible(&dvbdev_register_lock)) 324 mutex_lock(&dvbdev_register_lock);
327 return -ERESTARTSYS;
328 list_del (&adap->list_head); 325 list_del (&adap->list_head);
329 mutex_unlock(&dvbdev_register_lock); 326 mutex_unlock(&dvbdev_register_lock);
330 return 0; 327 return 0;