Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Jun 2000 22:11:37 +0100
From:      David Malone <dwmalone@maths.tcd.ie>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        freebsd-bugs@FreeBSD.org, archie@whistle.com
Subject:   Re: kern/18909: select(2) timeout limited to 100000000 seconds
Message-ID:  <20000612221136.A18521@walton.maths.tcd.ie>
In-Reply-To: <200006080840.BAA25083@freefall.freebsd.org>; from bde@zeta.org.au on Thu, Jun 08, 2000 at 01:40:03AM -0700
References:  <200006080840.BAA25083@freefall.freebsd.org>

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

I had a think about how to check for wraparound and negative times,
and (if you assume current time is positive anyway) I think you
can do both quite simply. You can just add the current time to the
select timeout passed in and then compare to check you got a time
in the future. If wraparound occured or if the timeout was negative
you'll get a time in the past.

The only other things itimerfix does I checked with a timevalvalid
macro, which probably belongs in sys/time.h? (I don't think the
min timeout thing needs to be done 'cos the callout stuff does that
for you).

I've just compiled a kernel with the following patch as a test and
it seems to be working. If it looks reasonable I can extend it to
similar bits of the kernel. (Almost identical code shows up in several
places, the patch below just covers select and poll).

[BTW - I just noticed that Archie's "How To Repeat" started with
"void main(".  Bad Bad Bad ;-)]

	David.

Index: sys_generic.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/kern/sys_generic.c,v
retrieving revision 1.56
diff -u -r1.56 sys_generic.c
--- sys_generic.c	2000/05/09 17:43:20	1.56
+++ sys_generic.c	2000/06/12 20:49:46
@@ -663,17 +663,24 @@
 	if (nbufbytes != 0)
 		bzero(selbits, nbufbytes / 2);
 
+#define timevalvalid(tvp)						\
+		( (tvp)->tv_usec >= 0 && (tvp)->tv_usec < 100000000 )
+
 	if (uap->tv) {
 		error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
 			sizeof (atv));
 		if (error)
 			goto done;
-		if (itimerfix(&atv)) {
+		if (!timevalvalid(&atv)) {
 			error = EINVAL;
 			goto done;
 		}
 		getmicrouptime(&rtv);
 		timevaladd(&atv, &rtv);
+		if (timevalcmp(&atv, &rtv, <)) { /* negative timeout/overflow */
+			error = EINVAL;
+			goto done;
+		}
 	} else
 		atv.tv_sec = 0;
 	timo = 0;
@@ -801,12 +808,16 @@
 	if (SCARG(uap, timeout) != INFTIM) {
 		atv.tv_sec = SCARG(uap, timeout) / 1000;
 		atv.tv_usec = (SCARG(uap, timeout) % 1000) * 1000;
-		if (itimerfix(&atv)) {
+		if (!timevalvalid(&atv)) {
 			error = EINVAL;
 			goto done;
 		}
 		getmicrouptime(&rtv);
 		timevaladd(&atv, &rtv);
+		if (timevalcmp(&atv, &rtv, <)) { /* negative timeout/overflow */
+			error = EINVAL;
+			goto done;
+		}
 	} else
 		atv.tv_sec = 0;
 	timo = 0;


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?20000612221136.A18521>