summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-05-14 10:54:57 +0000
committerkib <kib@FreeBSD.org>2009-05-14 10:54:57 +0000
commit7361db22793eeb694f1f01d466272bd47bac53d9 (patch)
tree045421c3780e4bded99ea72d2698157e8d6f2f89 /sys/kern
parente420c3ccc5cbe952d1fc43d6e05eb9f25a67bd5b (diff)
downloadFreeBSD-src-7361db22793eeb694f1f01d466272bd47bac53d9.zip
FreeBSD-src-7361db22793eeb694f1f01d466272bd47bac53d9.tar.gz
Do not advance req->oldidx when sysctl_old_user returning an
error due to copyout failure or short buffer. The later breaks the usermode iterators of the sysctl results that pack arbitrary number of variable-sized structures. Iterator expects that kernel filled exactly oldlen bytes, and tries to interpret half-filled or garbage structure at the end of the buffer. In particular, kinfo_getfile(3) segfaulted. Reported and tested by: pho MFC after: 3 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sysctl.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index b69ac8f..89fbb9a 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1221,9 +1221,9 @@ sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
if (i > 0)
bcopy(p, (char *)req->oldptr + req->oldidx, i);
}
- req->oldidx += l;
if (req->oldptr && i != l)
return (ENOMEM);
+ req->oldidx += l;
return (0);
}
@@ -1320,9 +1320,10 @@ sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
size_t i, len, origidx;
origidx = req->oldidx;
- req->oldidx += l;
- if (req->oldptr == NULL)
+ if (req->oldptr == NULL) {
+ req->oldidx += l;
return (0);
+ }
/*
* If we have not wired the user supplied buffer and we are currently
* holding locks, drop a witness warning, as it's possible that
@@ -1344,6 +1345,7 @@ sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
return (error);
if (i < l)
return (ENOMEM);
+ req->oldidx += l;
return (0);
}
OpenPOWER on IntegriCloud