summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-09-26 13:17:31 +0000
committerkib <kib@FreeBSD.org>2013-09-26 13:17:31 +0000
commit9a6c86c2977221f23d944238cdb2973a3630994f (patch)
treebf86fe1b615fbb275d1e27c1dc87faca0997ee06 /sys/kern/kern_event.c
parentc58dbf73e0a6e0d54f57e8c3b51b2b554625defe (diff)
downloadFreeBSD-src-9a6c86c2977221f23d944238cdb2973a3630994f.zip
FreeBSD-src-9a6c86c2977221f23d944238cdb2973a3630994f.tar.gz
Do not allow negative timeouts for kqueue timers, check for the
negative timeout both before and after the conversion to sbintime_t. For periodic kqueue timer, convert zero timeout into 1ms, to avoid interrupt storm on fast event timers. Reported and tested by: pho Discussed with: mav Reviewed by: davide Sponsored by: The FreeBSD Foundation Approved by: re (marius)
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index fe6f238..4c068bf 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -554,8 +554,17 @@ static int
filt_timerattach(struct knote *kn)
{
struct callout *calloutp;
+ sbintime_t to;
unsigned int ncallouts;
+ if ((intptr_t)kn->kn_sdata < 0)
+ return (EINVAL);
+ if ((intptr_t)kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0)
+ kn->kn_sdata = 1;
+ to = timer2sbintime(kn->kn_sdata);
+ if (to < 0)
+ return (EINVAL);
+
ncallouts = atomic_load_explicit(&kq_ncallouts, memory_order_relaxed);
do {
if (ncallouts >= kq_calloutmax)
@@ -569,8 +578,7 @@ filt_timerattach(struct knote *kn)
calloutp = malloc(sizeof(*calloutp), M_KQUEUE, M_WAITOK);
callout_init(calloutp, CALLOUT_MPSAFE);
kn->kn_hook = calloutp;
- callout_reset_sbt_on(calloutp,
- timer2sbintime(kn->kn_sdata), 0 /* 1ms? */,
+ callout_reset_sbt_on(calloutp, to, 0 /* 1ms? */,
filt_timerexpire, kn, PCPU_GET(cpuid), 0);
return (0);
OpenPOWER on IntegriCloud