Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Mar 2013 22:40:47 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r247903 - head/sys/kern
Message-ID:  <201303062240.r26MelaH095463@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Mar  6 22:40:47 2013
New Revision: 247903
URL: http://svnweb.freebsd.org/changeset/base/247903

Log:
  Reduce minimal time intervals of setitimer(2) from 1/HZ to 1/(16*HZ) by
  using callout_reset_sbt() instead of callout_reset().  We can't remove
  lower limit completely in this case because of significant processing
  overhead, caused by unability to use direct callout execution due to using
  process mutex in callout handler for sending SEGALRM signal.  With support
  of periodic events that would allow unprivileged user to abuse the system.
  
  Reviewed by:	davide

Modified:
  head/sys/kern/kern_time.c

Modified: head/sys/kern/kern_time.c
==============================================================================
--- head/sys/kern/kern_time.c	Wed Mar  6 22:12:45 2013	(r247902)
+++ head/sys/kern/kern_time.c	Wed Mar  6 22:40:47 2013	(r247903)
@@ -691,7 +691,7 @@ kern_getitimer(struct thread *td, u_int 
 		*aitv = p->p_realtimer;
 		PROC_UNLOCK(p);
 		if (timevalisset(&aitv->it_value)) {
-			getmicrouptime(&ctv);
+			microuptime(&ctv);
 			if (timevalcmp(&aitv->it_value, &ctv, <))
 				timevalclear(&aitv->it_value);
 			else
@@ -736,28 +736,33 @@ kern_setitimer(struct thread *td, u_int 
 {
 	struct proc *p = td->td_proc;
 	struct timeval ctv;
+	sbintime_t sbt, pr;
 
 	if (aitv == NULL)
 		return (kern_getitimer(td, which, oitv));
 
 	if (which > ITIMER_PROF)
 		return (EINVAL);
-	if (itimerfix(&aitv->it_value))
+	if (itimerfix(&aitv->it_value) ||
+	    aitv->it_value.tv_sec > INT32_MAX / 2)
 		return (EINVAL);
 	if (!timevalisset(&aitv->it_value))
 		timevalclear(&aitv->it_interval);
-	else if (itimerfix(&aitv->it_interval))
+	else if (itimerfix(&aitv->it_interval) ||
+	    aitv->it_interval.tv_sec > INT32_MAX / 2)
 		return (EINVAL);
 
 	if (which == ITIMER_REAL) {
 		PROC_LOCK(p);
 		if (timevalisset(&p->p_realtimer.it_value))
 			callout_stop(&p->p_itcallout);
-		getmicrouptime(&ctv);
+		microuptime(&ctv);
 		if (timevalisset(&aitv->it_value)) {
-			callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value),
-			    realitexpire, p);
+			pr = tvtosbt(aitv->it_value) >> tc_precexp;
 			timevaladd(&aitv->it_value, &ctv);
+			sbt = tvtosbt(aitv->it_value);
+			callout_reset_sbt(&p->p_itcallout, sbt, pr,
+			    realitexpire, p, C_ABSOLUTE);
 		}
 		*oitv = p->p_realtimer;
 		p->p_realtimer = *aitv;
@@ -793,7 +798,8 @@ void
 realitexpire(void *arg)
 {
 	struct proc *p;
-	struct timeval ctv, ntv;
+	struct timeval ctv;
+	sbintime_t isbt;
 
 	p = (struct proc *)arg;
 	kern_psignal(p, SIGALRM);
@@ -803,19 +809,17 @@ realitexpire(void *arg)
 			wakeup(&p->p_itcallout);
 		return;
 	}
-	for (;;) {
+	isbt = tvtosbt(p->p_realtimer.it_interval);
+	if (isbt >= sbt_timethreshold)
+		getmicrouptime(&ctv);
+	else
+		microuptime(&ctv);
+	do {
 		timevaladd(&p->p_realtimer.it_value,
 		    &p->p_realtimer.it_interval);
-		getmicrouptime(&ctv);
-		if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
-			ntv = p->p_realtimer.it_value;
-			timevalsub(&ntv, &ctv);
-			callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1,
-			    realitexpire, p);
-			return;
-		}
-	}
-	/*NOTREACHED*/
+	} while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=));
+	callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
+	    isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE);
 }
 
 /*
@@ -830,8 +834,9 @@ itimerfix(struct timeval *tv)
 
 	if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
 		return (EINVAL);
-	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
-		tv->tv_usec = tick;
+	if (tv->tv_sec == 0 && tv->tv_usec != 0 &&
+	    tv->tv_usec < (u_int)tick / 16)
+		tv->tv_usec = (u_int)tick / 16;
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303062240.r26MelaH095463>