aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2006-03-25 06:06:33 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-25 11:22:48 -0500
commitc08b8a49100715b20e6f7c997e992428b5e06078 (patch)
tree014758fb05908a3d49eeadc77f16dfa7585b12ac /arch/x86_64
parent185ae6d7a32721e9062030a9f2d24ed714fa45df (diff)
[PATCH] sys_alarm() unsigned signed conversion fixup
alarm() calls the kernel with an unsigend int timeout in seconds. The value is stored in the tv_sec field of a struct timeval to setup the itimer. The tv_sec field of struct timeval is of type long, which causes the tv_sec value to be negative on 32 bit machines if seconds > INT_MAX. Before the hrtimer merge (pre 2.6.16) such a negative value was converted to the maximum jiffies timeout by the timeval_to_jiffies conversion. It's not clear whether this was intended or just happened to be done by the timeval_to_jiffies code. hrtimers expect a timeval in canonical form and treat a negative timeout as already expired. This breaks the legitimate usage of alarm() with a timeout value > INT_MAX seconds. For 32 bit machines it is therefor necessary to limit the internal seconds value to avoid API breakage. Instead of doing this in all implementations of sys_alarm the duplicated sys_alarm code is moved into a common function in itimer.c Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/ia32/sys_ia32.c16
1 files changed, 2 insertions, 14 deletions
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 2bc55af95419..2b2d029f477c 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -430,24 +430,12 @@ put_tv32(struct compat_timeval __user *o, struct timeval *i)
430 return err; 430 return err;
431} 431}
432 432
433extern int do_setitimer(int which, struct itimerval *, struct itimerval *); 433extern unsigned int alarm_setitimer(unsigned int seconds);
434 434
435asmlinkage long 435asmlinkage long
436sys32_alarm(unsigned int seconds) 436sys32_alarm(unsigned int seconds)
437{ 437{
438 struct itimerval it_new, it_old; 438 return alarm_setitimer(seconds);
439 unsigned int oldalarm;
440
441 it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
442 it_new.it_value.tv_sec = seconds;
443 it_new.it_value.tv_usec = 0;
444 do_setitimer(ITIMER_REAL, &it_new, &it_old);
445 oldalarm = it_old.it_value.tv_sec;
446 /* ehhh.. We can't return 0 if we have an alarm pending.. */
447 /* And we'd better return too much than too little anyway */
448 if (it_old.it_value.tv_usec)
449 oldalarm++;
450 return oldalarm;
451} 439}
452 440
453/* Translations due to time_t size differences. Which affects all 441/* Translations due to time_t size differences. Which affects all