Module: xenomai-3 Branch: master Commit: ba218111ebea0ce19a47bb7f4802d79a20972e73 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=ba218111ebea0ce19a47bb7f4802d79a20972e73
Author: Philippe Gerum <r...@xenomai.org> Date: Thu Oct 16 14:41:12 2014 +0200 cobalt/posix/timerfd: prepare for 32bit syscall emulation --- kernel/cobalt/posix/timerfd.c | 102 +++++++++++++++++++++++------------------ kernel/cobalt/posix/timerfd.h | 7 +++ 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/kernel/cobalt/posix/timerfd.c b/kernel/cobalt/posix/timerfd.c index f994a22..7324ce9 100644 --- a/kernel/cobalt/posix/timerfd.c +++ b/kernel/cobalt/posix/timerfd.c @@ -43,9 +43,9 @@ struct cobalt_tfd { static ssize_t timerfd_read(struct rtdm_fd *fd, void __user *buf, size_t size) { - unsigned long long __user *u_ticks; - unsigned long long ticks = 0; struct cobalt_tfd *tfd; + __u64 __user *u_ticks; + __u64 ticks = 0; bool aligned; spl_t s; int err; @@ -54,6 +54,9 @@ static ssize_t timerfd_read(struct rtdm_fd *fd, void __user *buf, size_t size) return -EINVAL; u_ticks = buf; + if (!access_wok(u_ticks, sizeof(*u_ticks))) + return -EFAULT; + aligned = (((unsigned long)buf) & (sizeof(ticks) - 1)) == 0; tfd = container_of(fd, struct cobalt_tfd, fd); @@ -230,15 +233,12 @@ static inline void tfd_put(struct cobalt_tfd *tfd) rtdm_fd_put(&tfd->fd); } -COBALT_SYSCALL(timerfd_settime, primary, - int, (int fd, int flags, - const struct itimerspec __user *new_value, - struct itimerspec __user *old_value)) +int __cobalt_timerfd_settime(int fd, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue) { - struct itimerspec ovalue, value; struct cobalt_tfd *tfd; - int cflag; - int err; + int cflag, ret; spl_t s; if (flags & ~COBALT_TFD_SETTIME_FLAGS) @@ -248,57 +248,63 @@ COBALT_SYSCALL(timerfd_settime, primary, if (IS_ERR(tfd)) return PTR_ERR(tfd); - if (!new_value || - __xn_copy_from_user(&value, new_value, sizeof(value))) { - err = -EFAULT; - goto out; - } - cflag = (flags & TFD_TIMER_ABSTIME) ? TIMER_ABSTIME : 0; xnlock_get_irqsave(&nklock, s); + tfd->target = NULL; if (flags & TFD_WAKEUP) { tfd->target = xnthread_current(); if (tfd->target == NULL) { - err = -EPERM; - goto out_unlock; + ret = -EPERM; + goto out; } - } else - tfd->target = NULL; + } - if (old_value) - cobalt_xntimer_gettime(&tfd->timer, &ovalue); + if (ovalue) + __cobalt_timer_getval(&tfd->timer, ovalue); xntimer_set_sched(&tfd->timer, xnsched_current()); - err = cobalt_xntimer_settime(&tfd->timer, - clock_flag(cflag, tfd->clockid), &value); - out_unlock: + ret = __cobalt_timer_setval(&tfd->timer, + clock_flag(cflag, tfd->clockid), value); +out: xnlock_put_irqrestore(&nklock, s); - if (err == 0 && old_value && - __xn_copy_to_user(old_value, &ovalue, sizeof(ovalue))) { - xnlock_get_irqsave(&nklock, s); - xntimer_stop(&tfd->timer); - tfd->target = NULL; - xnlock_put_irqrestore(&nklock, s); + tfd_put(tfd); - err = -EFAULT; - } + return ret; +} - out: - tfd_put(tfd); +COBALT_SYSCALL(timerfd_settime, primary, + int, (int fd, int flags, + const struct itimerspec __user *new_value, + struct itimerspec __user *old_value)) +{ + struct itimerspec ovalue, value; + int ret; - return err; + ret = __xn_safe_copy_from_user(&value, new_value, sizeof(value)); + if (ret) + return ret; + + ret = __cobalt_timerfd_settime(fd, flags, &value, &ovalue); + if (ret) + return ret; + + if (old_value) { + ret = __xn_safe_copy_to_user(old_value, &ovalue, sizeof(ovalue)); + value.it_value.tv_sec = 0; + value.it_value.tv_nsec = 0; + __cobalt_timerfd_settime(fd, flags, &value, NULL); + } + + return ret; } -COBALT_SYSCALL(timerfd_gettime, current, - int, (int fd, struct itimerspec __user *curr_value)) +int __cobalt_timerfd_gettime(int fd, struct itimerspec *value) { - struct itimerspec value; struct cobalt_tfd *tfd; - int err = 0; spl_t s; tfd = tfd_get(fd); @@ -306,13 +312,21 @@ COBALT_SYSCALL(timerfd_gettime, current, return PTR_ERR(tfd); xnlock_get_irqsave(&nklock, s); - cobalt_xntimer_gettime(&tfd->timer, &value); + __cobalt_timer_getval(&tfd->timer, value); xnlock_put_irqrestore(&nklock, s); - if (!curr_value || __xn_copy_to_user(curr_value, &value, sizeof(value))) - err = -EFAULT; - tfd_put(tfd); - return err; + return 0; +} + +COBALT_SYSCALL(timerfd_gettime, current, + int, (int fd, struct itimerspec __user *curr_value)) +{ + struct itimerspec value; + int ret; + + ret = __cobalt_timerfd_gettime(fd, &value); + + return ret ?: __xn_safe_copy_to_user(curr_value, &value, sizeof(value)); } diff --git a/kernel/cobalt/posix/timerfd.h b/kernel/cobalt/posix/timerfd.h index ef1592c..1539254 100644 --- a/kernel/cobalt/posix/timerfd.h +++ b/kernel/cobalt/posix/timerfd.h @@ -4,6 +4,13 @@ #include <linux/time.h> #include <xenomai/posix/syscall.h> +int __cobalt_timerfd_settime(int fd, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value); + +int __cobalt_timerfd_gettime(int fd, + struct itimerspec *value); + COBALT_SYSCALL_DECL(timerfd_create, int, (int clockid, int flags)); _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git