Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/uvm Avoid locking issues when copying out requires takin...



details:   https://anonhg.NetBSD.org/src/rev/901bead239d4
branches:  trunk
changeset: 815691:901bead239d4
user:      christos <christos%NetBSD.org@localhost>
date:      Wed Jun 01 00:49:44 2016 +0000

description:
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.

diffstat:

 sys/uvm/uvm_map.c |  39 ++++++++++++++++++++++++++++-----------
 1 files changed, 28 insertions(+), 11 deletions(-)

diffs (91 lines):

diff -r f3e28360a98b -r 901bead239d4 sys/uvm/uvm_map.c
--- a/sys/uvm/uvm_map.c Wed Jun 01 00:47:16 2016 +0000
+++ b/sys/uvm/uvm_map.c Wed Jun 01 00:49:44 2016 +0000
@@ -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 @@
 {
        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 @@
        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;
 }
 



Home | Main Index | Thread Index | Old Index