Commit ac20427ef6aa63da663bdc88b71d16f7394f5e23

Authored by Neil Horman
Committed by Linus Torvalds
1 parent 3bc1ee3e8f

[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>

Showing 4 changed files with 24 additions and 5 deletions Side-by-side Diff

drivers/block/genhd.c
... ... @@ -40,7 +40,7 @@
40 40  
41 41 #ifdef CONFIG_PROC_FS
42 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 45 struct blk_major_name *n;
46 46 int i, len;
47 47  
48 48  
... ... @@ -49,10 +49,18 @@
49 49  
50 50 down(&block_subsys_sem);
51 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 59 len += sprintf(p+len, "%3d %s\n",
54 60 n->major, n->name);
  61 + }
55 62 }
  63 +page_full:
56 64 up(&block_subsys_sem);
57 65  
58 66 return len;
... ... @@ -56,10 +56,21 @@
56 56  
57 57 down(&chrdevs_lock);
58 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 69 len += sprintf(page+len, "%3d %s\n",
61 70 cd->major, cd->name);
  71 + }
62 72 }
  73 +page_full:
63 74 up(&chrdevs_lock);
64 75  
65 76 return len;
... ... @@ -451,7 +451,7 @@
451 451 int count, int *eof, void *data)
452 452 {
453 453 int len = get_chrdev_list(page);
454   - len += get_blkdev_list(page+len);
  454 + len += get_blkdev_list(page+len, len);
455 455 return proc_calc_metrics(page, start, off, count, eof, len);
456 456 }
457 457  
include/linux/genhd.h
... ... @@ -224,7 +224,7 @@
224 224 extern void disk_round_stats(struct gendisk *disk);
225 225  
226 226 /* drivers/block/genhd.c */
227   -extern int get_blkdev_list(char *);
  227 +extern int get_blkdev_list(char *, int);
228 228 extern void add_disk(struct gendisk *disk);
229 229 extern void del_gendisk(struct gendisk *gp);
230 230 extern void unlink_gendisk(struct gendisk *gp);