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.
|
* Copyright (c) 1997 Charles D. Cranor and Washington University.
|
||||||
@ -66,7 +66,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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_ddb.h"
|
||||||
#include "opt_uvmhist.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;
|
int error;
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
struct kinfo_vmentry vme;
|
struct kinfo_vmentry *vme;
|
||||||
struct vmspace *vm;
|
struct vmspace *vm;
|
||||||
struct vm_map *map;
|
struct vm_map *map;
|
||||||
struct vm_map_entry *entry;
|
struct vm_map_entry *entry;
|
||||||
char *dp;
|
char *dp;
|
||||||
size_t count;
|
size_t count, vmesize;
|
||||||
|
|
||||||
|
vme = NULL;
|
||||||
|
vmesize = *oldlenp;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
if (oldp && *oldlenp > 1024 * 1024)
|
||||||
|
return E2BIG;
|
||||||
|
|
||||||
if ((error = proc_find_locked(l, &p, pid)) != 0)
|
if ((error = proc_find_locked(l, &p, pid)) != 0)
|
||||||
return error;
|
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);
|
vm_map_lock_read(map);
|
||||||
|
|
||||||
dp = oldp;
|
dp = oldp;
|
||||||
|
if (oldp)
|
||||||
|
vme = kmem_alloc(vmesize, KM_SLEEP);
|
||||||
for (entry = map->header.next; entry != &map->header;
|
for (entry = map->header.next; entry != &map->header;
|
||||||
entry = entry->next) {
|
entry = entry->next) {
|
||||||
if (oldp && (dp - (char *)oldp) < *oldlenp + elem_size) {
|
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)
|
if (error)
|
||||||
break;
|
goto out;
|
||||||
error = sysctl_copyout(l, &vme, dp,
|
|
||||||
min(elem_size, sizeof(vme)));
|
|
||||||
if (error)
|
|
||||||
break;
|
|
||||||
dp += elem_size;
|
dp += elem_size;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
vm_map_unlock_read(map);
|
vm_map_unlock_read(map);
|
||||||
uvmspace_free(vm);
|
uvmspace_free(vm);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (pid != -1)
|
if (pid != -1)
|
||||||
mutex_exit(p->p_lock);
|
mutex_exit(p->p_lock);
|
||||||
if (error == 0) {
|
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;
|
count *= elem_size;
|
||||||
if (oldp != NULL && *oldlenp < count)
|
if (oldp != NULL && *oldlenp < count)
|
||||||
error = ENOSPC;
|
error = ENOSPC;
|
||||||
*oldlenp = count;
|
*oldlenp = count;
|
||||||
}
|
}
|
||||||
|
if (vme)
|
||||||
|
kmem_free(vme, vmesize);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user