Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Oct 2000 23:33:44 +0100
From:      David Malone <dwmalone@maths.tcd.ie>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        freebsd-bugs@FreeBSD.org, jlemon@FreeBSD.org, bp@FreeBSD.org, marcel@FreeBSD.org
Subject:   Re: kern/18909: select(2) timeout limited to 100000000 seconds
Message-ID:  <20001017233344.A88671@walton.maths.tcd.ie>
In-Reply-To: <20000612221136.A18521@walton.maths.tcd.ie>; from dwmalone@maths.tcd.ie on Mon, Jun 12, 2000 at 10:11:37PM %2B0100
References:  <200006080840.BAA25083@freefall.freebsd.org> <20000612221136.A18521@walton.maths.tcd.ie>

next in thread | previous in thread | raw e-mail | index | archive | help

I'd like to commit something along the lines of the following patch.
It removes calls to "itimerfix" for select, poll and other code
which has been copied from them.

Itimerfix limits the duration you can wait to 100000000 seconds,
which isn't needed in the cases I've looked at 'cos they know how
to sleep for a shorter amount of time and then go back to sleep
again if they have to wait for longer.

The crux of the change is a function timevaladdcheck which adds
two timevals but checks the sum won't overflow or underflow. I
think it avoids doing any calculations which might cause problems.

	David.

Index: compat/linux/linux_misc.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/compat/linux/linux_misc.c,v
retrieving revision 1.85
diff -u -r1.85 linux_misc.c
--- compat/linux/linux_misc.c	2000/08/26 05:08:10	1.85
+++ compat/linux/linux_misc.c	2000/10/17 14:41:04
@@ -457,7 +457,7 @@
 	printf("Linux-emul(%ld): incoming timeout (%ld/%ld)\n",
 	    (long)p->p_pid, utv.tv_sec, utv.tv_usec);
 #endif
-	if (itimerfix(&utv)) {
+	if (utv.tv_sec < 0 || utv.tv_usec < 0 || utv.tv_sec >= 1000000) {
 	    /*
 	     * The timeval was invalid.  Convert it to something
 	     * valid that will act as it does under Linux.
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/kern/kern_event.c,v
retrieving revision 1.16
diff -u -r1.16 kern_event.c
--- kern/kern_event.c	2000/08/30 04:49:07	1.16
+++ kern/kern_event.c	2000/10/17 14:51:34
@@ -525,17 +525,15 @@
 
 	if (tsp != NULL) {
 		TIMESPEC_TO_TIMEVAL(&atv, tsp);
-		if (itimerfix(&atv)) {
-			error = EINVAL;
-			goto done;
-		}
 		if (tsp->tv_sec == 0 && tsp->tv_nsec == 0)
 			timeout = -1;
 		else 
 			timeout = atv.tv_sec > 24 * 60 * 60 ?
 			    24 * 60 * 60 * hz : tvtohz(&atv);
 		getmicrouptime(&rtv);
-		timevaladd(&atv, &rtv);
+		error = timevaladdcheck(&atv, &rtv);
+		if (error)
+			goto done;
 	} else {
 		atv.tv_sec = 0;
 		atv.tv_usec = 0;
Index: kern/kern_time.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/kern/kern_time.c,v
retrieving revision 1.70
diff -u -r1.70 kern_time.c
--- kern/kern_time.c	2000/04/18 15:15:20	1.70
+++ kern/kern_time.c	2000/10/17 14:03:32
@@ -49,6 +49,8 @@
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
 
+#include <machine/limits.h>
+
 struct timezone tz;
 
 /*
@@ -656,6 +658,35 @@
 	t1->tv_sec -= t2->tv_sec;
 	t1->tv_usec -= t2->tv_usec;
 	timevalfix(t1);
+}
+
+int
+timevaladdcheck(t1, t2)
+	struct timeval *t1, *t2;
+{
+	struct timeval xtv;
+
+	if (t1->tv_usec < 0 || t1->tv_usec >= 1000000 ||
+	    t2->tv_usec < 0 || t2->tv_usec >= 1000000)
+		return EINVAL;
+
+	/* Check for underflow or overflow if result is not between t1 & t2 */
+	if (t1->tv_sec >= 0 && t2->tv_sec >= 0) {
+		xtv.tv_sec = LONG_MAX;
+		xtv.tv_usec = 999999;
+		timevalsub(&xtv, t1);
+		if (timevalcmp(t2, &xtv, >))
+			return EINVAL;
+	} else if (t1->tv_sec < 0 && t2->tv_sec < 0) {
+		xtv.tv_sec = LONG_MIN;
+		xtv.tv_usec = 0;
+		timevalsub(&xtv, t1);
+		if (timevalcmp(t2, &xtv, <))
+			return EINVAL;
+	}
+
+	timevaladd(t1, t2);
+	return 0;
 }
 
 static void
Index: kern/sys_generic.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/kern/sys_generic.c,v
retrieving revision 1.63
diff -u -r1.63 sys_generic.c
--- kern/sys_generic.c	2000/07/28 22:17:42	1.63
+++ kern/sys_generic.c	2000/10/17 14:18:09
@@ -692,12 +692,14 @@
 			sizeof (atv));
 		if (error)
 			goto done;
-		if (itimerfix(&atv)) {
+		getmicrouptime(&rtv);
+		error = timevaladdcheck(&atv, &rtv);
+		if (error)
+			goto done;
+		if (timevalcmp(&atv, &rtv, <)) {
 			error = EINVAL;
 			goto done;
 		}
-		getmicrouptime(&rtv);
-		timevaladd(&atv, &rtv);
 	} else {
 		atv.tv_sec = 0;
 		atv.tv_usec = 0;
@@ -827,12 +829,14 @@
 	if (SCARG(uap, timeout) != INFTIM) {
 		atv.tv_sec = SCARG(uap, timeout) / 1000;
 		atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
-		if (itimerfix(&atv)) {
+		getmicrouptime(&rtv);
+		error = timevaladdcheck(&atv, &rtv);
+		if (error)
+			goto done;
+		if (timevalcmp(&atv, &rtv, <)) {
 			error = EINVAL;
 			goto done;
 		}
-		getmicrouptime(&rtv);
-		timevaladd(&atv, &rtv);
 	} else {
 		atv.tv_sec = 0;
 		atv.tv_usec = 0;
Index: netncp/ncp_sock.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/netncp/ncp_sock.c,v
retrieving revision 1.2
diff -u -r1.2 ncp_sock.c
--- netncp/ncp_sock.c	1999/10/12 10:36:59	1.2
+++ netncp/ncp_sock.c	2000/10/17 14:30:34
@@ -203,12 +203,10 @@
 
 	if (tv) {
 		atv=*tv;
-		if (itimerfix(&atv)) {
-			error = EINVAL;
-			goto done;
-		}
 		getmicrouptime(&rtv);
-		timevaladd(&atv, &rtv);
+		error = timevaladdcheck(&atv, &rtv);
+		if (error)
+			goto done;
 	}
 	timo = 0;
 retry:
@@ -224,7 +222,8 @@
 			goto done;
 		ttv=atv;
 		timevalsub(&ttv, &rtv);
-		timo = tvtohz(&ttv);
+		timo = ttv.tv_sec > 24 * 60 * 60 ?
+		    24 * 60 * 60 * hz : tvtohz(&ttv);
 	}
 	s = splhigh();
 	if ((p->p_flag & P_SELECT) == 0) {
Index: sys/time.h
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/sys/time.h,v
retrieving revision 1.43
diff -u -r1.43 time.h
--- sys/time.h	2000/03/20 14:09:05	1.43
+++ sys/time.h	2000/10/17 13:47:49
@@ -199,6 +199,7 @@
 void	nanouptime __P((struct timespec *ts));
 void	nanotime __P((struct timespec *ts));
 void	timevaladd __P((struct timeval *, struct timeval *));
+int	timevaladdcheck __P((struct timeval *, struct timeval *));
 void	timevalsub __P((struct timeval *, struct timeval *));
 int	tvtohz __P((struct timeval *));
 #else /* !_KERNEL */


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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