summaryrefslogtreecommitdiffstats
path: root/lib/libkvm/kvm_proc.c
diff options
context:
space:
mode:
authordd <dd@FreeBSD.org>2002-04-07 04:47:58 +0000
committerdd <dd@FreeBSD.org>2002-04-07 04:47:58 +0000
commit4abe7f3290df6085a727b2653a0f55dea71c2427 (patch)
tree3691e102725bd0c84aadd0ae356e6b667a057338 /lib/libkvm/kvm_proc.c
parent9c4d69ea428a0d4a522b5299d3971e7f84c32b12 (diff)
downloadFreeBSD-src-4abe7f3290df6085a727b2653a0f55dea71c2427.zip
FreeBSD-src-4abe7f3290df6085a727b2653a0f55dea71c2427.tar.gz
Fix (for the second time) kvm_getprocs() for the case where no
processes match the given criteria. Since revision 1.60 of malloc.c, malloc() and friends return an invalid pointer when given a size of 0. kvm_getprocs() uses sysctl() with a NULL oldp argument to get an initial size, but does not check whether it's 0 before passing it to realloc() (via _kvm_realloc()). Before the aforementioned malloc() change, this resulted in a minimal allocation made and a valid poitner returned, but now results in an invalid, but non-NULL, pointer being returned. When this is passed to sysctl(), the latter returns EFAULT (as it should).
Diffstat (limited to 'lib/libkvm/kvm_proc.c')
-rw-r--r--lib/libkvm/kvm_proc.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index 2708a0a..865377c 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -409,6 +409,25 @@ kvm_getprocs(kd, op, arg, cnt)
_kvm_syserr(kd, kd->program, "kvm_getprocs");
return (0);
}
+ /*
+ * We can't continue with a size of 0 because we pass
+ * it to realloc() (via _kvm_realloc()), and passing 0
+ * to realloc() results in undefined behavior.
+ */
+ if (size == 0) {
+ /*
+ * XXX: We should probably return an invalid,
+ * but non-NULL, pointer here so any client
+ * program trying to dereference it will
+ * crash. However, _kvm_freeprocs() calls
+ * free() on kd->procbase if it isn't NULL,
+ * and free()'ing a junk pointer isn't good.
+ * Then again, _kvm_freeprocs() isn't used
+ * anywhere . . .
+ */
+ kd->procbase = _kvm_malloc(kd, 1);
+ goto liveout;
+ }
do {
size += size / 10;
kd->procbase = (struct kinfo_proc *)
@@ -422,6 +441,12 @@ kvm_getprocs(kd, op, arg, cnt)
_kvm_syserr(kd, kd->program, "kvm_getprocs");
return (0);
}
+ /*
+ * We have to check the size again because sysctl()
+ * may "round up" oldlenp if oldp is NULL; hence it
+ * might've told us that there was data to get when
+ * there really isn't any.
+ */
if (size > 0 &&
kd->procbase->ki_structsize != sizeof(struct kinfo_proc)) {
_kvm_err(kd, kd->program,
@@ -430,6 +455,7 @@ kvm_getprocs(kd, op, arg, cnt)
kd->procbase->ki_structsize);
return (0);
}
+liveout:
nprocs = size == 0 ? 0 : size / kd->procbase->ki_structsize;
} else {
struct nlist nl[4], *p;
OpenPOWER on IntegriCloud