diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2005-07-31 04:36:52 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2005-07-31 04:36:52 +0000 |
commit | 62d84ae7dbf17f958fadaf54eb348d051a02c678 (patch) | |
tree | bcc5021083f044d84180313f67e9af096b0ab56a /sys/kern/kern_sysctl.c | |
parent | 7f5924101ef06c4d3997b6942f55f0c64af1abaa (diff) |
do not allocate huge kinfo_proc2 and eproc structures on the stack.
allocate them on startup if needed, and free them when done.
discussion with pascoe, tested by dlg
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r-- | sys/kern/kern_sysctl.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index ac0e8d7dad5..f60cc100d65 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.127 2005/06/08 22:33:27 millert Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.128 2005/07/31 04:36:51 deraadt Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1018,8 +1018,8 @@ sysctl_doproc(name, namelen, where, sizep) char *where; size_t *sizep; { - struct kinfo_proc2 kproc2; - struct eproc eproc; + struct kinfo_proc2 *kproc2 = NULL; + struct eproc *eproc = NULL; struct proc *p; char *dp; int arg, buflen, doingzomb, elem_size, elem_count; @@ -1037,6 +1037,7 @@ sysctl_doproc(name, namelen, where, sizep) op = name[1]; arg = op == KERN_PROC_ALL ? 0 : name[2]; elem_size = elem_count = 0; + eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK); } else /* if (type == KERN_PROC2) */ { if (namelen != 5 || name[3] < 0 || name[4] < 0) return (EINVAL); @@ -1044,6 +1045,7 @@ sysctl_doproc(name, namelen, where, sizep) arg = name[2]; elem_size = name[3]; elem_count = name[4]; + kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK); } p = LIST_FIRST(&allproc); doingzomb = 0; @@ -1102,36 +1104,37 @@ again: /* no filtering */ break; default: - return (EINVAL); + error = EINVAL; + goto err; } if (type == KERN_PROC) { if (buflen >= sizeof(struct kinfo_proc)) { - fill_eproc(p, &eproc); + fill_eproc(p, eproc); error = copyout((caddr_t)p, &((struct kinfo_proc *)dp)->kp_proc, sizeof(struct proc)); if (error) - return (error); - error = copyout((caddr_t)&eproc, + goto err; + error = copyout((caddr_t)eproc, &((struct kinfo_proc *)dp)->kp_eproc, - sizeof(eproc)); + sizeof(*eproc)); if (error) - return (error); + goto err; dp += sizeof(struct kinfo_proc); buflen -= sizeof(struct kinfo_proc); } needed += sizeof(struct kinfo_proc); } else /* if (type == KERN_PROC2) */ { if (buflen >= elem_size && elem_count > 0) { - fill_kproc2(p, &kproc2); + fill_kproc2(p, kproc2); /* * Copy out elem_size, but not larger than * the size of a struct kinfo_proc2. */ - error = copyout(&kproc2, dp, - min(sizeof(kproc2), elem_size)); + error = copyout(kproc2, dp, + min(sizeof(*kproc2), elem_size)); if (error) - return (error); + goto err; dp += elem_size; buflen -= elem_size; elem_count--; @@ -1146,13 +1149,20 @@ again: } if (where != NULL) { *sizep = dp - where; - if (needed > *sizep) - return (ENOMEM); + if (needed > *sizep) { + error = ENOMEM; + goto err; + } } else { needed += KERN_PROCSLOP; *sizep = needed; } - return (0); +err: + if (eproc) + free(eproc, M_TEMP); + if (kproc2) + free(kproc2, M_TEMP); + return (error); } #endif /* SMALL_KERNEL */ |