forked from Minki/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>
This commit is contained in:
parent
3bc1ee3e8f
commit
ac20427ef6
@ -40,7 +40,7 @@ static inline int major_to_index(int major)
|
|||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
/* get block device names in somewhat random order */
|
/* 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;
|
struct blk_major_name *n;
|
||||||
int i, len;
|
int i, len;
|
||||||
@ -49,10 +49,18 @@ int get_blkdev_list(char *p)
|
|||||||
|
|
||||||
down(&block_subsys_sem);
|
down(&block_subsys_sem);
|
||||||
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
|
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",
|
len += sprintf(p+len, "%3d %s\n",
|
||||||
n->major, n->name);
|
n->major, n->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
page_full:
|
||||||
up(&block_subsys_sem);
|
up(&block_subsys_sem);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
@ -56,10 +56,21 @@ int get_chrdev_list(char *page)
|
|||||||
|
|
||||||
down(&chrdevs_lock);
|
down(&chrdevs_lock);
|
||||||
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
|
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",
|
len += sprintf(page+len, "%3d %s\n",
|
||||||
cd->major, cd->name);
|
cd->major, cd->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
page_full:
|
||||||
up(&chrdevs_lock);
|
up(&chrdevs_lock);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
@ -451,7 +451,7 @@ static int devices_read_proc(char *page, char **start, off_t off,
|
|||||||
int count, int *eof, void *data)
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = get_chrdev_list(page);
|
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);
|
return proc_calc_metrics(page, start, off, count, eof, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ static inline void free_disk_stats(struct gendisk *disk)
|
|||||||
extern void disk_round_stats(struct gendisk *disk);
|
extern void disk_round_stats(struct gendisk *disk);
|
||||||
|
|
||||||
/* drivers/block/genhd.c */
|
/* 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 add_disk(struct gendisk *disk);
|
||||||
extern void del_gendisk(struct gendisk *gp);
|
extern void del_gendisk(struct gendisk *gp);
|
||||||
extern void unlink_gendisk(struct gendisk *gp);
|
extern void unlink_gendisk(struct gendisk *gp);
|
||||||
|
Loading…
Reference in New Issue
Block a user