summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Blunck <j.blunck@tu-harburg.de>2005-08-23 22:25:14 +0200
committerChris Wright <chrisw@osdl.org>2005-08-29 09:55:13 -0700
commitec3b77ec116cf2b9d42f6544caa71f084cfc1ff1 (patch)
tree4dce860a2e4a886e5d2bbed3a44a8215e5ebe42c
parent7b1bfbc0786fdc9ba511d0136f6417736bdc4cc6 (diff)
[PATCH] sg.c: fix a memory leak in devices seq_file implementation (2nd)
I know that scsi procfs is legacy code but this is a fix for a memory leak. While reading through sg.c I realized that the implementation of /proc/scsi/sg/devices with seq_file is leaking memory due to freeing the pointer returned by the next() iterator method. Since next() might return NULL or an error this is wrong. This patch fixes it through using the seq_files private field for holding the reference to the iterator object. Here is a small bash script to trigger the leak. Use slabtop to watch the size-32 usage grow and grow. #!/bin/sh while true; do cat /proc/scsi/sg/devices > /dev/null done Signed-off-by: Jan Blunck <j.blunck@tu-harburg.de> Signed-off-by: Chris Wright <chrisw@osdl.org>
-rw-r--r--drivers/scsi/sg.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7936aafc3d05..7db9f19d47cd 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2969,23 +2969,22 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos)
{
struct sg_proc_deviter * it = kmalloc(sizeof(*it), GFP_KERNEL);
+ s->private = it;
if (! it)
return NULL;
+
if (NULL == sg_dev_arr)
- goto err1;
+ return NULL;
it->index = *pos;
it->max = sg_last_dev();
if (it->index >= it->max)
- goto err1;
+ return NULL;
return it;
-err1:
- kfree(it);
- return NULL;
}
static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
- struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
+ struct sg_proc_deviter * it = s->private;
*pos = ++it->index;
return (it->index < it->max) ? it : NULL;
@@ -2993,7 +2992,9 @@ static void * dev_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void dev_seq_stop(struct seq_file *s, void *v)
{
- kfree (v);
+ struct sg_proc_deviter * it = s->private;
+
+ kfree (it);
}
static int sg_proc_open_dev(struct inode *inode, struct file *file)