garbage in /proc/partitions (kernel 2.4.20)

From: Jonathan Brassow (brassow@sistina.com)
Date: Mon May 05 2003 - 11:58:30 EST


There is garbage in the /proc/partions "file" when the partition
information exceeds the page size. It is a problem that lies in the
interaction between linux/fs/seq_file.c:seq_read() and the
seq_operations defined in linux/drivers/block/genhd.c.

I believe that the offending is in the following section of seq_read():
         /* we need at least one record in buffer */
         while (1) {
                 pos = m->index;
                 p = m->op->start(m, &pos);
                 err = PTR_ERR(p);
                 if (!p || IS_ERR(p))
                         break;
                 err = m->op->show(m, p);
                 if (err)
                         break;
                 if (m->count < m->size)
                         goto Fill;
                 m->op->stop(m, p);
                 kfree(m->buf);
                 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
                 if (!m->buf)
                         goto Enomem;
         }

What seems to happen is that the partition information does not fit in
m-buf, so 2x the amount of memory is allocated. However, "count"
doesn't seem to be reset, so really, there is still only one page to
use instead of two (count points to the end of the first page). Again
we malloc more space - this time 4 pages worth. Count is still not
reset, but now we have 2 pages worth of space to use and the operations
succeed. When the buffer is copied to user space, we have a whole
bunch of garbage, followed by the correct information.

On the surface, it would appear that the right thing to do is set
"count" to zero at the end of the while loop.
diff -urN linux-2.4.20/fs/seq_file.c linux-2.4.20-patched/fs/seq_file.c
--- linux-2.4.20/fs/seq_file.c Sat Nov 17 20:16:22 2001
+++ linux-2.4.20-patched/fs/seq_file.c Fri May 2 14:16:41 2003
@@ -94,6 +94,7 @@
                 m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
                 if (!m->buf)
                         goto Enomem;
+ m->count = 0;
         }
         m->op->stop(m, p);
         goto Done;

This solves the problem for /proc/partitions, but I am not completely
clear on exactly who is at fault here, so this may be the wrong thing
to do...

I have attached examples to illustrate the problem (my apologies if
this makes the mail larger than what is generally accepted). In the
first, the partition information weighs in under the page size and
displays correctly. In the second, the partition information is > the
page size and garbage gets included.

thanks,
  brassow






-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed May 07 2003 - 22:00:22 EST