From 3bccc0f766d1e99e7bb0fda86328af28446049c0 Mon Sep 17 00:00:00 2001 From: christos Date: Fri, 25 Jul 2008 17:40:24 +0000 Subject: [PATCH] Handle files with a large number of mappings gracefully. Reported by Nicholas Joly. --- sys/miscfs/procfs/procfs_map.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/sys/miscfs/procfs/procfs_map.c b/sys/miscfs/procfs/procfs_map.c index b17136fce1aa..2f1d38b2f681 100644 --- a/sys/miscfs/procfs/procfs_map.c +++ b/sys/miscfs/procfs/procfs_map.c @@ -1,4 +1,4 @@ -/* $NetBSD: procfs_map.c,v 1.34 2007/12/15 23:52:00 christos Exp $ */ +/* $NetBSD: procfs_map.c,v 1.35 2008/07/25 17:40:24 christos Exp $ */ /* * Copyright (c) 1993 @@ -76,7 +76,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: procfs_map.c,v 1.34 2007/12/15 23:52:00 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: procfs_map.c,v 1.35 2008/07/25 17:40:24 christos Exp $"); #include #include @@ -92,6 +92,7 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_map.c,v 1.34 2007/12/15 23:52:00 christos Exp #include #define BUFFERSIZE (64 * 1024) +#define MAXBUFFERSIZE (256 * 1024) /* * The map entries can *almost* be read with programs like cat. However, @@ -111,7 +112,8 @@ procfs_domap(struct lwp *curl, struct proc *p, struct pfsnode *pfs, struct vmspace *vm; struct vm_map *map; struct vm_map_entry *entry; - char *buffer; + char *buffer = NULL; + size_t bufsize = BUFFERSIZE; char *path; struct vnode *vp; struct vattr va; @@ -133,7 +135,6 @@ procfs_domap(struct lwp *curl, struct proc *p, struct pfsnode *pfs, error = 0; - buffer = malloc(BUFFERSIZE, M_TEMP, M_WAITOK); if (linuxmode != 0) path = malloc(MAXPATHLEN * 4, M_TEMP, M_WAITOK); else @@ -145,6 +146,8 @@ procfs_domap(struct lwp *curl, struct proc *p, struct pfsnode *pfs, map = &vm->vm_map; vm_map_lock_read(map); +again: + buffer = malloc(bufsize, M_TEMP, M_WAITOK); pos = 0; for (entry = map->header.next; entry != &map->header; entry = entry->next) { @@ -195,6 +198,15 @@ procfs_domap(struct lwp *curl, struct proc *p, struct pfsnode *pfs, entry->inheritance, entry->wired_count, entry->advice); } + if (pos >= bufsize) { + bufsize <<= 1; + if (bufsize > MAXBUFFERSIZE) { + error = ENOMEM; + goto out; + } + free(buffer, M_TEMP); + goto again; + } } vm_map_unlock_read(map);