diff options
author | Dima Dorfman <dd@FreeBSD.org> | 2002-04-07 04:47:58 +0000 |
---|---|---|
committer | Dima Dorfman <dd@FreeBSD.org> | 2002-04-07 04:47:58 +0000 |
commit | 21687047cfdb5d37345a0fb5605fd91d7ee75700 (patch) | |
tree | 3691e102725bd0c84aadd0ae356e6b667a057338 /lib/libkvm | |
parent | 92c07aa8801b75c61ee3d034fe420b7211166001 (diff) | |
download | src-21687047cfdb5d37345a0fb5605fd91d7ee75700.tar.gz src-21687047cfdb5d37345a0fb5605fd91d7ee75700.zip |
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).
Notes
Notes:
svn path=/head/; revision=94028
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 2708a0a9414b..865377c97ab0 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; |