summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2006-05-20 22:55:47 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2006-05-20 22:55:47 +0000
commit1b0cbdff78b1cfa0fe3816a8d43e30ce11646c51 (patch)
tree7a010e54168e08472bdf9686ed8647af4ca15164 /sys/kern
parentf8e7d10b85514bec7a8d6c91c901756a72cf26f2 (diff)
It is possible for a sensor to be detached and freed while it is being
copied out to userland. If this happens we get a use after free and things blow up. Prevent this by making a local copy of the sensor that cannot be freed elsewhere in the kernel and copying that out instead. found by mbalmer@ ok deraadt@ krw@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_sysctl.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 6c521f2e00a..0b153df579c 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.140 2006/05/08 22:51:18 gwk Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.141 2006/05/20 22:55:46 dlg Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -1796,19 +1796,22 @@ int
sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
- struct sensor *s;
- int num;
+ struct sensor ls, *s;
if (namelen != 1)
return (ENOTDIR);
- num = name[0];
-
- s = sensor_get(num);
+ s = sensor_get(name[0]);
if (s == NULL)
return (ENOENT);
- return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
+ /*
+ * Make a local copy of the sensor which cannot be freed by a driver
+ * while it's being copied to userland.
+ */
+ bcopy(s, &ls, sizeof(ls));
+
+ return (sysctl_rdstruct(oldp, oldlenp, newp, &ls, sizeof(ls)));
}
int