From 4abe7f3290df6085a727b2653a0f55dea71c2427 Mon Sep 17 00:00:00 2001 From: dd Date: Sun, 7 Apr 2002 04:47:58 +0000 Subject: 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). --- lib/libkvm/kvm_proc.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'lib/libkvm/kvm_proc.c') 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; -- cgit v1.1