Loading fs/compat.c +0 −41 Original line number Diff line number Diff line Loading @@ -1737,47 +1737,6 @@ asmlinkage long compat_sys_signalfd(int ufd, } #endif /* CONFIG_SIGNALFD */ #ifdef CONFIG_TIMERFD asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, const struct compat_itimerspec __user *utmr, struct compat_itimerspec __user *otmr) { int error; struct itimerspec t; struct itimerspec __user *ut; if (get_compat_itimerspec(&t, utmr)) return -EFAULT; ut = compat_alloc_user_space(2 * sizeof(struct itimerspec)); if (copy_to_user(&ut[0], &t, sizeof(t))) return -EFAULT; error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]); if (!error && otmr) error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) || put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; return error; } asmlinkage long compat_sys_timerfd_gettime(int ufd, struct compat_itimerspec __user *otmr) { int error; struct itimerspec t; struct itimerspec __user *ut; ut = compat_alloc_user_space(sizeof(struct itimerspec)); error = sys_timerfd_gettime(ufd, ut); if (!error) error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) || put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; return error; } #endif /* CONFIG_TIMERFD */ #ifdef CONFIG_FHANDLE /* * Exactly like fs/open.c:sys_open_by_handle_at(), except that it Loading fs/timerfd.c +66 −19 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/anon_inodes.h> #include <linux/timerfd.h> #include <linux/syscalls.h> #include <linux/compat.h> #include <linux/rcupdate.h> struct timerfd_ctx { Loading Loading @@ -278,21 +279,17 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) return ufd; } SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) static int do_timerfd_settime(int ufd, int flags, const struct itimerspec *new, struct itimerspec *old) { struct fd f; struct timerfd_ctx *ctx; struct itimerspec ktmr, kotmr; int ret; if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) return -EFAULT; if ((flags & ~TFD_SETTIME_FLAGS) || !timespec_valid(&ktmr.it_value) || !timespec_valid(&ktmr.it_interval)) !timespec_valid(&new->it_value) || !timespec_valid(&new->it_interval)) return -EINVAL; ret = timerfd_fget(ufd, &f); Loading Loading @@ -323,27 +320,23 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, if (ctx->expired && ctx->tintv.tv64) hrtimer_forward_now(&ctx->tmr, ctx->tintv); kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); kotmr.it_interval = ktime_to_timespec(ctx->tintv); old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); old->it_interval = ktime_to_timespec(ctx->tintv); /* * Re-program the timer to the new value ... */ ret = timerfd_setup(ctx, flags, &ktmr); ret = timerfd_setup(ctx, flags, new); spin_unlock_irq(&ctx->wqh.lock); fdput(f); if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr))) return -EFAULT; return ret; } SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) static int do_timerfd_gettime(int ufd, struct itimerspec *t) { struct fd f; struct timerfd_ctx *ctx; struct itimerspec kotmr; int ret = timerfd_fget(ufd, &f); if (ret) return ret; Loading @@ -356,11 +349,65 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; hrtimer_restart(&ctx->tmr); } kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); kotmr.it_interval = ktime_to_timespec(ctx->tintv); t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); t->it_interval = ktime_to_timespec(ctx->tintv); spin_unlock_irq(&ctx->wqh.lock); fdput(f); return 0; } SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) { struct itimerspec new, old; int ret; if (copy_from_user(&new, utmr, sizeof(new))) return -EFAULT; ret = do_timerfd_settime(ufd, flags, &new, &old); if (ret) return ret; if (otmr && copy_to_user(otmr, &old, sizeof(old))) return -EFAULT; return ret; } SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) { struct itimerspec kotmr; int ret = do_timerfd_gettime(ufd, &kotmr); if (ret) return ret; return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; } #ifdef COMPAT COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) { struct itimerspec new, old; int ret; if (get_compat_itimerspec(&new, utmr)) return -EFAULT; ret = do_timerfd_settime(ufd, flags, &new, &old); if (ret) return ret; if (otmr && put_compat_itimerspec(otmr, &old)) return -EFAULT; return ret; } COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) { struct itimerspec kotmr; int ret = do_timerfd_gettime(ufd, &kotmr); if (ret) return ret; return put_compat_itimerspec(otmr, &t) ? -EFAULT: 0; } #endif Loading
fs/compat.c +0 −41 Original line number Diff line number Diff line Loading @@ -1737,47 +1737,6 @@ asmlinkage long compat_sys_signalfd(int ufd, } #endif /* CONFIG_SIGNALFD */ #ifdef CONFIG_TIMERFD asmlinkage long compat_sys_timerfd_settime(int ufd, int flags, const struct compat_itimerspec __user *utmr, struct compat_itimerspec __user *otmr) { int error; struct itimerspec t; struct itimerspec __user *ut; if (get_compat_itimerspec(&t, utmr)) return -EFAULT; ut = compat_alloc_user_space(2 * sizeof(struct itimerspec)); if (copy_to_user(&ut[0], &t, sizeof(t))) return -EFAULT; error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]); if (!error && otmr) error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) || put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; return error; } asmlinkage long compat_sys_timerfd_gettime(int ufd, struct compat_itimerspec __user *otmr) { int error; struct itimerspec t; struct itimerspec __user *ut; ut = compat_alloc_user_space(sizeof(struct itimerspec)); error = sys_timerfd_gettime(ufd, ut); if (!error) error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) || put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0; return error; } #endif /* CONFIG_TIMERFD */ #ifdef CONFIG_FHANDLE /* * Exactly like fs/open.c:sys_open_by_handle_at(), except that it Loading
fs/timerfd.c +66 −19 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <linux/anon_inodes.h> #include <linux/timerfd.h> #include <linux/syscalls.h> #include <linux/compat.h> #include <linux/rcupdate.h> struct timerfd_ctx { Loading Loading @@ -278,21 +279,17 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) return ufd; } SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) static int do_timerfd_settime(int ufd, int flags, const struct itimerspec *new, struct itimerspec *old) { struct fd f; struct timerfd_ctx *ctx; struct itimerspec ktmr, kotmr; int ret; if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) return -EFAULT; if ((flags & ~TFD_SETTIME_FLAGS) || !timespec_valid(&ktmr.it_value) || !timespec_valid(&ktmr.it_interval)) !timespec_valid(&new->it_value) || !timespec_valid(&new->it_interval)) return -EINVAL; ret = timerfd_fget(ufd, &f); Loading Loading @@ -323,27 +320,23 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, if (ctx->expired && ctx->tintv.tv64) hrtimer_forward_now(&ctx->tmr, ctx->tintv); kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); kotmr.it_interval = ktime_to_timespec(ctx->tintv); old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); old->it_interval = ktime_to_timespec(ctx->tintv); /* * Re-program the timer to the new value ... */ ret = timerfd_setup(ctx, flags, &ktmr); ret = timerfd_setup(ctx, flags, new); spin_unlock_irq(&ctx->wqh.lock); fdput(f); if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr))) return -EFAULT; return ret; } SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) static int do_timerfd_gettime(int ufd, struct itimerspec *t) { struct fd f; struct timerfd_ctx *ctx; struct itimerspec kotmr; int ret = timerfd_fget(ufd, &f); if (ret) return ret; Loading @@ -356,11 +349,65 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; hrtimer_restart(&ctx->tmr); } kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); kotmr.it_interval = ktime_to_timespec(ctx->tintv); t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); t->it_interval = ktime_to_timespec(ctx->tintv); spin_unlock_irq(&ctx->wqh.lock); fdput(f); return 0; } SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) { struct itimerspec new, old; int ret; if (copy_from_user(&new, utmr, sizeof(new))) return -EFAULT; ret = do_timerfd_settime(ufd, flags, &new, &old); if (ret) return ret; if (otmr && copy_to_user(otmr, &old, sizeof(old))) return -EFAULT; return ret; } SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) { struct itimerspec kotmr; int ret = do_timerfd_gettime(ufd, &kotmr); if (ret) return ret; return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; } #ifdef COMPAT COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, const struct itimerspec __user *, utmr, struct itimerspec __user *, otmr) { struct itimerspec new, old; int ret; if (get_compat_itimerspec(&new, utmr)) return -EFAULT; ret = do_timerfd_settime(ufd, flags, &new, &old); if (ret) return ret; if (otmr && put_compat_itimerspec(otmr, &old)) return -EFAULT; return ret; } COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) { struct itimerspec kotmr; int ret = do_timerfd_gettime(ufd, &kotmr); if (ret) return ret; return put_compat_itimerspec(otmr, &t) ? -EFAULT: 0; } #endif