diff options
author | Neil Horman <nhorman@redhat.com> | 2005-06-23 03:09:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-23 12:45:19 -0400 |
commit | ac20427ef6aa63da663bdc88b71d16f7394f5e23 (patch) | |
tree | 49ba4f88c5cea42d59b386c508174f585efc8a01 | |
parent | 3bc1ee3e8f1c05c0f64a479c6d56eb34a6190599 (diff) |
[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>
-rw-r--r-- | drivers/block/genhd.c | 12 | ||||
-rw-r--r-- | fs/char_dev.c | 13 | ||||
-rw-r--r-- | fs/proc/proc_misc.c | 2 | ||||
-rw-r--r-- | include/linux/genhd.h | 2 |
4 files changed, 24 insertions, 5 deletions
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index 43805e4d31e9..47fd3659a061 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c | |||
@@ -40,7 +40,7 @@ static inline int major_to_index(int major) | |||
40 | 40 | ||
41 | #ifdef CONFIG_PROC_FS | 41 | #ifdef CONFIG_PROC_FS |
42 | /* get block device names in somewhat random order */ | 42 | /* get block device names in somewhat random order */ |
43 | int get_blkdev_list(char *p) | 43 | int get_blkdev_list(char *p, int used) |
44 | { | 44 | { |
45 | struct blk_major_name *n; | 45 | struct blk_major_name *n; |
46 | int i, len; | 46 | int i, len; |
@@ -49,10 +49,18 @@ int get_blkdev_list(char *p) | |||
49 | 49 | ||
50 | down(&block_subsys_sem); | 50 | down(&block_subsys_sem); |
51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { | 51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { |
52 | for (n = major_names[i]; n; n = n->next) | 52 | for (n = major_names[i]; n; n = n->next) { |
53 | /* | ||
54 | * If the curent string plus the 5 extra characters | ||
55 | * in the line would run us off the page, then we're done | ||
56 | */ | ||
57 | if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) | ||
58 | goto page_full; | ||
53 | len += sprintf(p+len, "%3d %s\n", | 59 | len += sprintf(p+len, "%3d %s\n", |
54 | n->major, n->name); | 60 | n->major, n->name); |
61 | } | ||
55 | } | 62 | } |
63 | page_full: | ||
56 | up(&block_subsys_sem); | 64 | up(&block_subsys_sem); |
57 | 65 | ||
58 | return len; | 66 | return len; |
diff --git a/fs/char_dev.c b/fs/char_dev.c index c1e3537909fc..e82aac9cc2f5 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -56,10 +56,21 @@ int get_chrdev_list(char *page) | |||
56 | 56 | ||
57 | down(&chrdevs_lock); | 57 | down(&chrdevs_lock); |
58 | for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { | 58 | for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { |
59 | for (cd = chrdevs[i]; cd; cd = cd->next) | 59 | for (cd = chrdevs[i]; cd; cd = cd->next) { |
60 | /* | ||
61 | * if the current name, plus the 5 extra characters | ||
62 | * in the device line for this entry | ||
63 | * would run us off the page, we're done | ||
64 | */ | ||
65 | if ((len+strlen(cd->name) + 5) >= PAGE_SIZE) | ||
66 | goto page_full; | ||
67 | |||
68 | |||
60 | len += sprintf(page+len, "%3d %s\n", | 69 | len += sprintf(page+len, "%3d %s\n", |
61 | cd->major, cd->name); | 70 | cd->major, cd->name); |
71 | } | ||
62 | } | 72 | } |
73 | page_full: | ||
63 | up(&chrdevs_lock); | 74 | up(&chrdevs_lock); |
64 | 75 | ||
65 | return len; | 76 | return len; |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 63a9fbf1ac51..94b570ad037d 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
@@ -451,7 +451,7 @@ static int devices_read_proc(char *page, char **start, off_t off, | |||
451 | int count, int *eof, void *data) | 451 | int count, int *eof, void *data) |
452 | { | 452 | { |
453 | int len = get_chrdev_list(page); | 453 | int len = get_chrdev_list(page); |
454 | len += get_blkdev_list(page+len); | 454 | len += get_blkdev_list(page+len, len); |
455 | return proc_calc_metrics(page, start, off, count, eof, len); | 455 | return proc_calc_metrics(page, start, off, count, eof, len); |
456 | } | 456 | } |
457 | 457 | ||
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index af26dc718ef6..01796c41c951 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -224,7 +224,7 @@ static inline void free_disk_stats(struct gendisk *disk) | |||
224 | extern void disk_round_stats(struct gendisk *disk); | 224 | extern void disk_round_stats(struct gendisk *disk); |
225 | 225 | ||
226 | /* drivers/block/genhd.c */ | 226 | /* drivers/block/genhd.c */ |
227 | extern int get_blkdev_list(char *); | 227 | extern int get_blkdev_list(char *, int); |
228 | extern void add_disk(struct gendisk *disk); | 228 | extern void add_disk(struct gendisk *disk); |
229 | extern void del_gendisk(struct gendisk *gp); | 229 | extern void del_gendisk(struct gendisk *gp); |
230 | extern void unlink_gendisk(struct gendisk *gp); | 230 | extern void unlink_gendisk(struct gendisk *gp); |