summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_sysctl.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index c165bb3e1686..639789361670 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1237,6 +1237,7 @@ ogetkerninfo(struct proc *p, struct getkerninfo_args *uap)
{
int error, name[6];
size_t size;
+ u_int needed = 0;
switch (uap->op & 0xff00) {
@@ -1300,16 +1301,15 @@ ogetkerninfo(struct proc *p, struct getkerninfo_args *uap)
* this is pretty crude, but it's just enough for uname()
* from BSDI's 1.x libc to work.
*
- * In particular, it doesn't return the same results when
- * the supplied buffer is too small. BSDI's version apparently
- * will return the amount copied, and set the *size to how
- * much was needed. The emulation framework here isn't capable
- * of that, so we just set both to the amount copied.
- * BSDI's 2.x product apparently fails with ENOMEM in this
- * scenario.
+ * *size gives the size of the buffer before the call, and
+ * the amount of data copied after a successful call.
+ * If successful, the return value is the amount of data
+ * available, which can be larger than *size.
+ *
+ * BSDI's 2.x product apparently fails with ENOMEM if *size
+ * is too small.
*/
- u_int needed;
u_int left;
char *s;
@@ -1332,13 +1332,15 @@ ogetkerninfo(struct proc *p, struct getkerninfo_args *uap)
needed = sizeof(bsdi_si) + (s - bsdi_strings);
- if (uap->where == NULL) {
+ if ((uap->where == NULL) || (uap->size == NULL)) {
/* process is asking how much buffer to supply.. */
size = needed;
error = 0;
break;
}
+ if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
+ break;
/* if too much buffer supplied, trim it down */
if (size > needed)
@@ -1364,7 +1366,7 @@ ogetkerninfo(struct proc *p, struct getkerninfo_args *uap)
}
if (error)
return (error);
- p->p_retval[0] = size;
+ p->p_retval[0] = needed ? needed : size;
if (uap->size)
error = copyout((caddr_t)&size, (caddr_t)uap->size,
sizeof(size));