patch to fix set_itimer() behaviour in boundary cases

From: Matthias Lang
Date: Sat Jan 15 2005 - 03:48:18 EST


Hi,

The linux implementation of setitimer() doesn't behave quite as
expected. I found several problems:

1. POSIX says that negative times should cause setitimer() to
return -1 and set errno to EINVAL. In linux, the call succeeds.

2. POSIX says that time values with usec >= 1000000 should
cause the same behaviour. In linux, the call succeeds.

3. If large time values are given, linux quietly truncates them
to the maximum time representable in jiffies. On 2.4.4 on PPC,
that's about 248 days. On 2.6.10 on x86, that's about 24 days.

POSIX doesn't really say what to do in this case, but looking at
established practice, i.e. "what BSD does", since the call comes
from BSD, *BSD returns -1 if the time is out of range.

References:

kernel/itimer.c
http://www.opengroup.org/onlinepubs/009695399/functions/getitimer.html
http://www.delorie.com/gnu/docs/glibc/libc_444.html
http://www.gsp.com/cgi-bin/man.cgi?section=2&topic=setitimer

I have tested on 2.4.4 and 2.6.10 as well as getting other people to
test on 2.4.28, 2.4.27 and FreeBSD.

Here's a patch against linux 2.6.10:

--- linux-2.6.10/kernel/itimer.c 2005-01-15 09:39:13.000000000 +0100
+++ linux-2.6.10.fixed/kernel/itimer.c 2005-01-13 09:56:50.000000000 +0100
@@ -84,6 +84,16 @@
register unsigned long i, j;
int k;

+ if (value->it_interval.tv_sec >= MAX_SEC_IN_JIFFIES
+ || value->it_value.tv_sec >= MAX_SEC_IN_JIFFIES
+ || value->it_interval.tv_sec < 0
+ || value->it_value.tv_sec < 0
+ || value->it_interval.tv_usec >= 1000000
+ || value->it_value.tv_usec >= 1000000
+ || value->it_interval.tv_usec < 0
+ || value->it_value.tv_usec < 0)
+ return -EINVAL;
+
i = timeval_to_jiffies(&value->it_interval);
j = timeval_to_jiffies(&value->it_value);
if (ovalue && (k = do_getitimer(which, ovalue)) < 0)

I've put it at http://www.corelatus.com/~matthias/posix_setitimer.patch
along with a test program, http://www.corelatus.com/~matthias/ti.c

Here's what the test program looks like when run on a patched 2.6.10 kernel:

tmp >gcc -Wall ti.c
tmp >./a.out
value sec=0 usec=0 result=0 expected=0
interval sec=0 usec=0 result=0 expected=0
value sec=1 usec=0 result=0 expected=0
interval sec=1 usec=0 result=0 expected=0
value sec=-1 usec=0 result=-1 expected=-1
interval sec=-1 usec=0 result=-1 expected=-1
value sec=0 usec=-1 result=-1 expected=-1
interval sec=0 usec=-1 result=-1 expected=-1
value sec=0 usec=1000000 result=-1 expected=-1
interval sec=0 usec=1000000 result=-1 expected=-1
value sec=0 usec=999999 result=0 expected=0
interval sec=0 usec=999999 result=0 expected=0
limit is 2147156
value sec=2147155 usec=0 result=0 expected=0
interval sec=2147155 usec=0 result=0 expected=0
value sec=2147156 usec=0 result=0 expected=0
interval sec=2147156 usec=0 result=0 expected=0
value sec=2147157 usec=0 result=-1 expected=-1
interval sec=2147157 usec=0 result=-1 expected=-1
All tests passed

Matt
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/