[linux-dvb] [PATCH] Memory leak in dem

Trent Piepho xyzzy at speakeasy.org
Mon Mar 27 23:42:25 CEST 2006


There is a memory lead in the demuxer, it's possible to open the dvr0 device
several times, each time after the first will leak the dvr buffer.  This patch
fixes that by only allowing a single read mode open, which is what the API says
should be the case.  It's still possible to open multiple times in write mode.
This doesn't seem to cause a problem and could be a useful thing to do.  It
would allow separate processes/threads to send audio/video/subtitles to a
decoder.

This is my first time using mercurial, so hopefully I got the patch format
correct.
-------------- next part --------------
# HG changeset patch
# User xyzzy at t2.domain.actdsltmp
# Node ID 6396b65320e33fa6507622cbf58f6c0d2bf0da1f
# Parent  e4f6344a95f9b9027f555f95dfa2e6af023d95e4
Fix memory leak in dvr open

From: Trent Piepho <xyzzy at speakeasy.org>

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 at speakeasy.org>

diff -r e4f6344a95f9 -r 6396b65320e3 linux/drivers/media/dvb/dvb-core/dmxdev.c
--- a/linux/drivers/media/dvb/dvb-core/dmxdev.c	Mon Mar 27 11:00:40 2006 -0300
+++ b/linux/drivers/media/dvb/dvb-core/dmxdev.c	Mon Mar 27 13:31:49 2006 -0800
@@ -141,12 +141,18 @@ static int dvb_dvr_open(struct inode *in
 	}
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		void *mem = vmalloc(DVR_BUFFER_SIZE);
+		void *mem;
+		if (!dvbdev->readers) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EBUSY;
+		}
+		mem = vmalloc(DVR_BUFFER_SIZE);
 		if (!mem) {
 			mutex_unlock(&dmxdev->mutex);
 			return -ENOMEM;
 		}
 		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+		dvbdev->readers--;
 	}
 
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
@@ -184,6 +190,7 @@ static int dvb_dvr_release(struct inode 
 						dmxdev->dvr_orig_fe);
 	}
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		dvbdev->readers++;
 		if (dmxdev->dvr_buffer.data) {
 			void *mem = dmxdev->dvr_buffer.data;
 			mb();
@@ -1029,8 +1036,7 @@ static struct file_operations dvb_dvr_fo
 
 static struct dvb_device dvbdev_dvr = {
 	.priv = NULL,
-	.users = 1,
-	.writers = 1,
+	.readers = 1,
 	.fops = &dvb_dvr_fops
 };
 


More information about the linux-dvb mailing list