[PATCH] add check to /proc/devices read routines
Patch to add check to get_chrdev_list and get_blkdev_list to prevent reads
of /proc/devices from spilling over the provided page if more than 4096
bytes of string data are generated from all the registered character and
block devices in a system
Signed-off-by: Neil Horman <nhorman@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 43805e4..47fd365 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -40,7 +40,7 @@
#ifdef CONFIG_PROC_FS
/* get block device names in somewhat random order */
-int get_blkdev_list(char *p)
+int get_blkdev_list(char *p, int used)
{
struct blk_major_name *n;
int i, len;
@@ -49,10 +49,18 @@
down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
- for (n = major_names[i]; n; n = n->next)
+ for (n = major_names[i]; n; n = n->next) {
+ /*
+ * If the curent string plus the 5 extra characters
+ * in the line would run us off the page, then we're done
+ */
+ if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
+ goto page_full;
len += sprintf(p+len, "%3d %s\n",
n->major, n->name);
+ }
}
+page_full:
up(&block_subsys_sem);
return len;
diff --git a/fs/char_dev.c b/fs/char_dev.c
index c1e3537..e82aac9 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -56,10 +56,21 @@
down(&chrdevs_lock);
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
- for (cd = chrdevs[i]; cd; cd = cd->next)
+ for (cd = chrdevs[i]; cd; cd = cd->next) {
+ /*
+ * if the current name, plus the 5 extra characters
+ * in the device line for this entry
+ * would run us off the page, we're done
+ */
+ if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
+ goto page_full;
+
+
len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name);
+ }
}
+page_full:
up(&chrdevs_lock);
return len;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 63a9fbf..94b570a 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -451,7 +451,7 @@
int count, int *eof, void *data)
{
int len = get_chrdev_list(page);
- len += get_blkdev_list(page+len);
+ len += get_blkdev_list(page+len, len);
return proc_calc_metrics(page, start, off, count, eof, len);
}
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index af26dc7..01796c4 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -224,7 +224,7 @@
extern void disk_round_stats(struct gendisk *disk);
/* drivers/block/genhd.c */
-extern int get_blkdev_list(char *);
+extern int get_blkdev_list(char *, int);
extern void add_disk(struct gendisk *disk);
extern void del_gendisk(struct gendisk *gp);
extern void unlink_gendisk(struct gendisk *gp);