From: Andi Kleen Add 32bit->64bit conversion functions for POSIX timers. I kept timer_create architecture specific, becauseit does signal specific stuff which is not portable enough for generic compat. Only lightly tested currently. include/linux/compat.h | 5 + kernel/compat.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff -puN include/linux/compat.h~compat-posix-timers include/linux/compat.h --- 25/include/linux/compat.h~compat-posix-timers 2003-08-10 14:49:29.000000000 -0700 +++ 25-akpm/include/linux/compat.h 2003-08-10 14:49:29.000000000 -0700 @@ -15,6 +15,11 @@ #define compat_jiffies_to_clock_t(x) \ (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) +struct compat_itimerspec { + struct compat_timespec it_interval; + struct compat_timespec it_value; +}; + struct compat_utimbuf { compat_time_t actime; compat_time_t modtime; diff -puN kernel/compat.c~compat-posix-timers kernel/compat.c --- 25/kernel/compat.c~compat-posix-timers 2003-08-10 14:49:29.000000000 -0700 +++ 25-akpm/kernel/compat.c 2003-08-10 14:49:29.000000000 -0700 @@ -430,3 +430,130 @@ asmlinkage int compat_sys_sched_getaffin return ret; } +static int get_compat_itimerspec(struct itimerspec *dst, + struct compat_itimerspec *src) +{ + if (get_compat_timespec(&dst->it_interval, &src->it_interval) || + get_compat_timespec(&dst->it_value, &src->it_value)) + return -EFAULT; + return 0; +} + +static int put_compat_itimerspec(struct compat_itimerspec *dst, + struct itimerspec *src) +{ + if (put_compat_timespec(&src->it_interval, &dst->it_interval) || + put_compat_timespec(&src->it_value, &dst->it_value)) + return -EFAULT; + return 0; +} + +extern asmlinkage long sys_timer_settime(timer_t timer_id, int flags, + struct itimerspec __user *new_setting, + struct itimerspec __user *old_setting); +extern asmlinkage long sys_timer_gettime(timer_t timer_id, + struct itimerspec __user *setting); + +long compat_timer_settime(timer_t timer_id, int flags, + struct compat_itimerspec *new, + struct compat_itimerspec *old) +{ + long err; + mm_segment_t oldfs; + struct itimerspec newts, oldts; + if (get_compat_itimerspec(&newts, new)) + return -EFAULT; + oldfs = get_fs(); + err = sys_timer_settime(timer_id, flags, &newts, &oldts); + set_fs(oldfs); + if (!err && old && put_compat_itimerspec(old, &oldts)) + return -EFAULT; + return err; +} + +long compat_timer_gettime(timer_t timer_id, struct compat_itimerspec *setting) +{ + long err; + mm_segment_t oldfs; + struct itimerspec ts; + oldfs = get_fs(); + err = sys_timer_gettime(timer_id, &ts); + set_fs(oldfs); + if (!err && put_compat_itimerspec(setting, &ts)) + return -EFAULT; + return err; +} + +extern asmlinkage long +sys_clock_settime(clockid_t which_clock, struct timespec __user *tp); + +long compat_clock_settime(clockid_t which_clock, struct compat_timespec *tp) +{ + long err; + mm_segment_t oldfs; + struct timespec ts; + if (get_compat_timespec(&ts, tp)) + return -EFAULT; + oldfs = get_fs(); + err = sys_clock_settime(which_clock, &ts); + set_fs(oldfs); + return err; +} + +extern asmlinkage long +sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp); + +long compat_clock_gettime(clockid_t which_clock, struct compat_timespec *tp) +{ + long err; + mm_segment_t oldfs; + struct timespec ts; + oldfs = get_fs(); + err = sys_clock_gettime(which_clock, &ts); + set_fs(oldfs); + if (!err && put_compat_timespec(&ts, tp)) + return -EFAULT; + return err; +} + +extern asmlinkage long +sys_clock_getres(clockid_t which_clock, struct timespec __user *tp); + +long compat_clock_getres(clockid_t which_clock, struct compat_timespec *tp) +{ + long err; + mm_segment_t oldfs; + struct timespec ts; + oldfs = get_fs(); + err = sys_clock_getres(which_clock, &ts); + set_fs(oldfs); + if (!err && put_compat_timespec(&ts, tp)) + return -EFAULT; + return err; +} + +extern asmlinkage long +sys_clock_nanosleep(clockid_t which_clock, int flags, + struct timespec __user *rqtp, + struct timespec __user *rmtp); + +long compat_clock_nanosleep(clockid_t which_clock, int flags, + struct compat_timespec __user *rqtp, + struct compat_timespec __user *rmtp) +{ + long err; + mm_segment_t oldfs; + struct timespec in, out; + if (get_compat_timespec(&in, rqtp)) + return -EFAULT; + oldfs = get_fs(); + err = sys_clock_nanosleep(which_clock, flags, &in, &out); + set_fs(oldfs); + if ((err == -ERESTART_RESTARTBLOCK) && rmtp && + put_compat_timespec(&out, rmtp)) + return -EFAULT; + return err; +} + +/* timer_create is architecture specific because it needs sigevent conversion */ + _