aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2006-03-30 13:53:32 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-04-02 03:56:01 -0400
commit5e85bd057f0cb29881e3d55d29f48bb55bd2f450 (patch)
tree7d1e582b25710d70487d1dc59e150b387a58c919 /drivers/media
parent2f03ee8e6bd7c6f40a1a0583662308e002d357da (diff)
V4L/DVB (3672): Fix memory leak in dvr open
The dvr device could be opened multiple times simultaneously in O_RDONLY mode. Each open after the first would allocate a new dvr buffer (1880 KB) and leak the old buffer. The first close would de-allocate the dvr buffer and cause all other open dvrs to stop working. This patch allows only a single O_RDONLY open of the drv device, as per the API specification. Multiple O_WRONLY opens are still allowed and don't appear to cause any problems. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 09e96e9ddbdf..04578df3f249 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -141,12 +141,18 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
141 } 141 }
142 142
143 if ((file->f_flags & O_ACCMODE) == O_RDONLY) { 143 if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
144 void *mem = vmalloc(DVR_BUFFER_SIZE); 144 void *mem;
145 if (!dvbdev->readers) {
146 mutex_unlock(&dmxdev->mutex);
147 return -EBUSY;
148 }
149 mem = vmalloc(DVR_BUFFER_SIZE);
145 if (!mem) { 150 if (!mem) {
146 mutex_unlock(&dmxdev->mutex); 151 mutex_unlock(&dmxdev->mutex);
147 return -ENOMEM; 152 return -ENOMEM;
148 } 153 }
149 dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE); 154 dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
155 dvbdev->readers--;
150 } 156 }
151 157
152 if ((file->f_flags & O_ACCMODE) == O_WRONLY) { 158 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
@@ -184,6 +190,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
184 dmxdev->dvr_orig_fe); 190 dmxdev->dvr_orig_fe);
185 } 191 }
186 if ((file->f_flags & O_ACCMODE) == O_RDONLY) { 192 if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
193 dvbdev->readers++;
187 if (dmxdev->dvr_buffer.data) { 194 if (dmxdev->dvr_buffer.data) {
188 void *mem = dmxdev->dvr_buffer.data; 195 void *mem = dmxdev->dvr_buffer.data;
189 mb(); 196 mb();
@@ -1029,8 +1036,7 @@ static struct file_operations dvb_dvr_fops = {
1029 1036
1030static struct dvb_device dvbdev_dvr = { 1037static struct dvb_device dvbdev_dvr = {
1031 .priv = NULL, 1038 .priv = NULL,
1032 .users = 1, 1039 .readers = 1,
1033 .writers = 1,
1034 .fops = &dvb_dvr_fops 1040 .fops = &dvb_dvr_fops
1035}; 1041};
1036 1042