diff options
| author | Simon Arlott <simon@fire.lp0.eu> | 2007-03-10 04:21:25 -0500 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-03-27 07:45:54 -0400 |
| commit | c278850206fd9df0bb62a72ca0b277fe20c5a452 (patch) | |
| tree | 439ae68737b5bcb5d473b3d12c3d5417f697ccb3 | |
| parent | b10fece583fdfdb3d2f29b0da3896ec58b8fe122 (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.c | 12 | ||||
| -rw-r--r-- | drivers/media/dvb/dvb-core/dvb_demux.c | 21 | ||||
| -rw-r--r-- | drivers/media/dvb/dvb-core/dvbdev.c | 9 |
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) | |||
| 673 | static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, | 672 | static 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 | ||
| 324 | int dvb_unregister_adapter(struct dvb_adapter *adap) | 322 | int 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; |
