Module Name: src
Committed By: christos
Date: Wed Mar 15 20:25:41 UTC 2017
Modified Files:
src/sys/uvm: uvm_map.c
Log Message:
PR/52078: Don't panic on 0 allocation, check more bounds.
To generate a diff of this commit:
cvs rdiff -u -r1.342 -r1.343 src/sys/uvm/uvm_map.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/uvm/uvm_map.c
diff -u src/sys/uvm/uvm_map.c:1.342 src/sys/uvm/uvm_map.c:1.343
--- src/sys/uvm/uvm_map.c:1.342 Wed Nov 30 21:09:03 2016
+++ src/sys/uvm/uvm_map.c Wed Mar 15 16:25:41 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_map.c,v 1.342 2016/12/01 02:09:03 mrg Exp $ */
+/* $NetBSD: uvm_map.c,v 1.343 2017/03/15 20:25:41 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.342 2016/12/01 02:09:03 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.343 2017/03/15 20:25:41 christos Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@@ -4892,15 +4892,25 @@ fill_vmentries(struct lwp *l, pid_t pid,
char *dp;
size_t count, vmesize;
- vme = NULL;
- vmesize = *oldlenp;
- count = 0;
- if (oldp && *oldlenp > 1024 * 1024)
- return E2BIG;
+ if (elem_size == 0 || elem_size > 2 * sizeof(*vme))
+ return EINVAL;
+
+ if (oldp) {
+ if (*oldlenp > 1024 * 1024)
+ return E2BIG;
+ count = *oldlenp / elem_size;
+ if (count == 0)
+ return ENOMEM;
+ vmesize = count * sizeof(*vme);
+ } else
+ vmesize = 0;
if ((error = proc_find_locked(l, &p, pid)) != 0)
return error;
+ vme = NULL;
+ count = 0;
+
if ((error = proc_vmspace_getref(p, &vm)) != 0)
goto out;
@@ -4912,7 +4922,7 @@ fill_vmentries(struct lwp *l, pid_t pid,
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) {
+ if (oldp && (dp - (char *)oldp) < *oldlenp) {
error = fill_vmentry(l, p, &vme[count], map, entry);
if (error)
goto out;
@@ -4930,8 +4940,7 @@ out:
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)
- {
+ if (oldp && (dp - (char *)oldp) < *oldlenp) {
error = sysctl_copyout(l, &vme[i], dp, esize);
if (error)
break;
@@ -4965,8 +4974,7 @@ sysctl_vmproc(SYSCTLFN_ARGS)
if (namelen != 3)
return EINVAL;
sysctl_unlock();
- error = fill_vmentries(l, name[1], name[2],
- oldp, oldlenp);
+ error = fill_vmentries(l, name[1], name[2], oldp, oldlenp);
sysctl_relock();
return error;
default: