From owner-freebsd-bugs  Tue Oct 17 15:33:53 2000
Delivered-To: freebsd-bugs@freebsd.org
Received: from salmon.maths.tcd.ie (salmon.maths.tcd.ie [134.226.81.11])
	by hub.freebsd.org (Postfix) with SMTP
	id A758B37B479; Tue, 17 Oct 2000 15:33:46 -0700 (PDT)
Received: from walton.maths.tcd.ie by salmon.maths.tcd.ie with SMTP
          id <aa65883@salmon>; 17 Oct 2000 23:33:45 +0100 (BST)
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>
References: <200006080840.BAA25083@freefall.freebsd.org> <20000612221136.A18521@walton.maths.tcd.ie>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2.5i
In-Reply-To: <20000612221136.A18521@walton.maths.tcd.ie>; from dwmalone@maths.tcd.ie on Mon, Jun 12, 2000 at 10:11:37PM +0100
Sender: owner-freebsd-bugs@FreeBSD.ORG
Precedence: bulk
X-Loop: FreeBSD.org


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