Avoid locking issues when copying out requires taking a fault and we are
finding out our own maps, by allocating a buffer and copying out after we collected the information.
This commit is contained in:
parent
71229fdd60
commit
bafdaf94ba
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uvm_map.c,v 1.337 2016/05/25 17:43:58 christos Exp $ */
|
||||
/* $NetBSD: uvm_map.c,v 1.338 2016/06/01 00:49:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Charles D. Cranor and Washington University.
|
||||
@ -66,7 +66,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.337 2016/05/25 17:43:58 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.338 2016/06/01 00:49:44 christos Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_uvmhist.h"
|
||||
@ -4877,14 +4877,18 @@ fill_vmentries(struct lwp *l, pid_t pid, u_int elem_size, void *oldp,
|
||||
{
|
||||
int error;
|
||||
struct proc *p;
|
||||
struct kinfo_vmentry vme;
|
||||
struct kinfo_vmentry *vme;
|
||||
struct vmspace *vm;
|
||||
struct vm_map *map;
|
||||
struct vm_map_entry *entry;
|
||||
char *dp;
|
||||
size_t count;
|
||||
size_t count, vmesize;
|
||||
|
||||
vme = NULL;
|
||||
vmesize = *oldlenp;
|
||||
count = 0;
|
||||
if (oldp && *oldlenp > 1024 * 1024)
|
||||
return E2BIG;
|
||||
|
||||
if ((error = proc_find_locked(l, &p, pid)) != 0)
|
||||
return error;
|
||||
@ -4896,31 +4900,44 @@ fill_vmentries(struct lwp *l, pid_t pid, u_int elem_size, void *oldp,
|
||||
vm_map_lock_read(map);
|
||||
|
||||
dp = oldp;
|
||||
if (oldp)
|
||||
vme = kmem_alloc(vmesize, KM_SLEEP);
|
||||
for (entry = map->header.next; entry != &map->header;
|
||||
entry = entry->next) {
|
||||
if (oldp && (dp - (char *)oldp) < *oldlenp + elem_size) {
|
||||
error = fill_vmentry(l, p, &vme, map, entry);
|
||||
error = fill_vmentry(l, p, &vme[count], map, entry);
|
||||
if (error)
|
||||
break;
|
||||
error = sysctl_copyout(l, &vme, dp,
|
||||
min(elem_size, sizeof(vme)));
|
||||
if (error)
|
||||
break;
|
||||
goto out;
|
||||
dp += elem_size;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
vm_map_unlock_read(map);
|
||||
uvmspace_free(vm);
|
||||
|
||||
out:
|
||||
if (pid != -1)
|
||||
mutex_exit(p->p_lock);
|
||||
if (error == 0) {
|
||||
const u_int esize = min(sizeof(*vme), elem_size);
|
||||
dp = oldp;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (oldp && (dp - (char *)oldp) < *oldlenp + elem_size)
|
||||
{
|
||||
error = sysctl_copyout(l, &vme[i], dp, esize);
|
||||
if (error)
|
||||
break;
|
||||
dp += elem_size;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
count *= elem_size;
|
||||
if (oldp != NULL && *oldlenp < count)
|
||||
error = ENOSPC;
|
||||
*oldlenp = count;
|
||||
}
|
||||
if (vme)
|
||||
kmem_free(vme, vmesize);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user