aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/compat.c41
-rw-r--r--fs/timerfd.c85
2 files changed, 66 insertions, 60 deletions
diff --git a/fs/compat.c b/fs/compat.c
index f9e2fe3794fa..fe40fde29111 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1737,47 +1737,6 @@ asmlinkage long compat_sys_signalfd(int ufd,
1737} 1737}
1738#endif /* CONFIG_SIGNALFD */ 1738#endif /* CONFIG_SIGNALFD */
1739 1739
1740#ifdef CONFIG_TIMERFD
1741
1742asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
1743 const struct compat_itimerspec __user *utmr,
1744 struct compat_itimerspec __user *otmr)
1745{
1746 int error;
1747 struct itimerspec t;
1748 struct itimerspec __user *ut;
1749
1750 if (get_compat_itimerspec(&t, utmr))
1751 return -EFAULT;
1752 ut = compat_alloc_user_space(2 * sizeof(struct itimerspec));
1753 if (copy_to_user(&ut[0], &t, sizeof(t)))
1754 return -EFAULT;
1755 error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]);
1756 if (!error && otmr)
1757 error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) ||
1758 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
1759
1760 return error;
1761}
1762
1763asmlinkage long compat_sys_timerfd_gettime(int ufd,
1764 struct compat_itimerspec __user *otmr)
1765{
1766 int error;
1767 struct itimerspec t;
1768 struct itimerspec __user *ut;
1769
1770 ut = compat_alloc_user_space(sizeof(struct itimerspec));
1771 error = sys_timerfd_gettime(ufd, ut);
1772 if (!error)
1773 error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) ||
1774 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
1775
1776 return error;
1777}
1778
1779#endif /* CONFIG_TIMERFD */
1780
1781#ifdef CONFIG_FHANDLE 1740#ifdef CONFIG_FHANDLE
1782/* 1741/*
1783 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it 1742 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
diff --git a/fs/timerfd.c b/fs/timerfd.c
index d03822bbf190..0e606b12a59d 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -22,6 +22,7 @@
22#include <linux/anon_inodes.h> 22#include <linux/anon_inodes.h>
23#include <linux/timerfd.h> 23#include <linux/timerfd.h>
24#include <linux/syscalls.h> 24#include <linux/syscalls.h>
25#include <linux/compat.h>
25#include <linux/rcupdate.h> 26#include <linux/rcupdate.h>
26 27
27struct timerfd_ctx { 28struct timerfd_ctx {
@@ -278,21 +279,17 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
278 return ufd; 279 return ufd;
279} 280}
280 281
281SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, 282static int do_timerfd_settime(int ufd, int flags,
282 const struct itimerspec __user *, utmr, 283 const struct itimerspec *new,
283 struct itimerspec __user *, otmr) 284 struct itimerspec *old)
284{ 285{
285 struct fd f; 286 struct fd f;
286 struct timerfd_ctx *ctx; 287 struct timerfd_ctx *ctx;
287 struct itimerspec ktmr, kotmr;
288 int ret; 288 int ret;
289 289
290 if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
291 return -EFAULT;
292
293 if ((flags & ~TFD_SETTIME_FLAGS) || 290 if ((flags & ~TFD_SETTIME_FLAGS) ||
294 !timespec_valid(&ktmr.it_value) || 291 !timespec_valid(&new->it_value) ||
295 !timespec_valid(&ktmr.it_interval)) 292 !timespec_valid(&new->it_interval))
296 return -EINVAL; 293 return -EINVAL;
297 294
298 ret = timerfd_fget(ufd, &f); 295 ret = timerfd_fget(ufd, &f);
@@ -323,27 +320,23 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
323 if (ctx->expired && ctx->tintv.tv64) 320 if (ctx->expired && ctx->tintv.tv64)
324 hrtimer_forward_now(&ctx->tmr, ctx->tintv); 321 hrtimer_forward_now(&ctx->tmr, ctx->tintv);
325 322
326 kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); 323 old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
327 kotmr.it_interval = ktime_to_timespec(ctx->tintv); 324 old->it_interval = ktime_to_timespec(ctx->tintv);
328 325
329 /* 326 /*
330 * Re-program the timer to the new value ... 327 * Re-program the timer to the new value ...
331 */ 328 */
332 ret = timerfd_setup(ctx, flags, &ktmr); 329 ret = timerfd_setup(ctx, flags, new);
333 330
334 spin_unlock_irq(&ctx->wqh.lock); 331 spin_unlock_irq(&ctx->wqh.lock);
335 fdput(f); 332 fdput(f);
336 if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr)))
337 return -EFAULT;
338
339 return ret; 333 return ret;
340} 334}
341 335
342SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) 336static int do_timerfd_gettime(int ufd, struct itimerspec *t)
343{ 337{
344 struct fd f; 338 struct fd f;
345 struct timerfd_ctx *ctx; 339 struct timerfd_ctx *ctx;
346 struct itimerspec kotmr;
347 int ret = timerfd_fget(ufd, &f); 340 int ret = timerfd_fget(ufd, &f);
348 if (ret) 341 if (ret)
349 return ret; 342 return ret;
@@ -356,11 +349,65 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
356 hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; 349 hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1;
357 hrtimer_restart(&ctx->tmr); 350 hrtimer_restart(&ctx->tmr);
358 } 351 }
359 kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); 352 t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
360 kotmr.it_interval = ktime_to_timespec(ctx->tintv); 353 t->it_interval = ktime_to_timespec(ctx->tintv);
361 spin_unlock_irq(&ctx->wqh.lock); 354 spin_unlock_irq(&ctx->wqh.lock);
362 fdput(f); 355 fdput(f);
356 return 0;
357}
358
359SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
360 const struct itimerspec __user *, utmr,
361 struct itimerspec __user *, otmr)
362{
363 struct itimerspec new, old;
364 int ret;
365
366 if (copy_from_user(&new, utmr, sizeof(new)))
367 return -EFAULT;
368 ret = do_timerfd_settime(ufd, flags, &new, &old);
369 if (ret)
370 return ret;
371 if (otmr && copy_to_user(otmr, &old, sizeof(old)))
372 return -EFAULT;
373
374 return ret;
375}
363 376
377SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr)
378{
379 struct itimerspec kotmr;
380 int ret = do_timerfd_gettime(ufd, &kotmr);
381 if (ret)
382 return ret;
364 return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; 383 return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
365} 384}
366 385
386#ifdef COMPAT
387COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
388 const struct itimerspec __user *, utmr,
389 struct itimerspec __user *, otmr)
390{
391 struct itimerspec new, old;
392 int ret;
393
394 if (get_compat_itimerspec(&new, utmr))
395 return -EFAULT;
396 ret = do_timerfd_settime(ufd, flags, &new, &old);
397 if (ret)
398 return ret;
399 if (otmr && put_compat_itimerspec(otmr, &old))
400 return -EFAULT;
401 return ret;
402}
403
404COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd,
405 struct itimerspec __user *, otmr)
406{
407 struct itimerspec kotmr;
408 int ret = do_timerfd_gettime(ufd, &kotmr);
409 if (ret)
410 return ret;
411 return put_compat_itimerspec(otmr, &t) ? -EFAULT: 0;
412}
413#endif