diff options
author | dd <dd@FreeBSD.org> | 2002-04-07 04:47:58 +0000 |
---|---|---|
committer | dd <dd@FreeBSD.org> | 2002-04-07 04:47:58 +0000 |
commit | 4abe7f3290df6085a727b2653a0f55dea71c2427 (patch) | |
tree | 3691e102725bd0c84aadd0ae356e6b667a057338 /lib/libkvm | |
parent | 9c4d69ea428a0d4a522b5299d3971e7f84c32b12 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | lib/libkvm/kvm_proc.c | 26 |
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; |