Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Neil Horman and committed by
Linus Torvalds
ac20427e 3bc1ee3e

+24 -5
+10 -2
drivers/block/genhd.c
··· 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; ··· 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;
+12 -1
fs/char_dev.c
··· 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;
+1 -1
fs/proc/proc_misc.c
··· 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
+1 -1
include/linux/genhd.h
··· 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);