diff options
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r-- | kernel/posix-timers.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 69185ae6b701..6edbb2c55c22 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -552,24 +552,22 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock, | |||
552 | return -EAGAIN; | 552 | return -EAGAIN; |
553 | 553 | ||
554 | spin_lock_init(&new_timer->it_lock); | 554 | spin_lock_init(&new_timer->it_lock); |
555 | retry: | 555 | |
556 | if (unlikely(!idr_pre_get(&posix_timers_id, GFP_KERNEL))) { | 556 | idr_preload(GFP_KERNEL); |
557 | error = -EAGAIN; | ||
558 | goto out; | ||
559 | } | ||
560 | spin_lock_irq(&idr_lock); | 557 | spin_lock_irq(&idr_lock); |
561 | error = idr_get_new(&posix_timers_id, new_timer, &new_timer_id); | 558 | error = idr_alloc(&posix_timers_id, new_timer, 0, 0, GFP_NOWAIT); |
562 | spin_unlock_irq(&idr_lock); | 559 | spin_unlock_irq(&idr_lock); |
563 | if (error) { | 560 | idr_preload_end(); |
564 | if (error == -EAGAIN) | 561 | if (error < 0) { |
565 | goto retry; | ||
566 | /* | 562 | /* |
567 | * Weird looking, but we return EAGAIN if the IDR is | 563 | * Weird looking, but we return EAGAIN if the IDR is |
568 | * full (proper POSIX return value for this) | 564 | * full (proper POSIX return value for this) |
569 | */ | 565 | */ |
570 | error = -EAGAIN; | 566 | if (error == -ENOSPC) |
567 | error = -EAGAIN; | ||
571 | goto out; | 568 | goto out; |
572 | } | 569 | } |
570 | new_timer_id = error; | ||
573 | 571 | ||
574 | it_id_set = IT_ID_SET; | 572 | it_id_set = IT_ID_SET; |
575 | new_timer->it_id = (timer_t) new_timer_id; | 573 | new_timer->it_id = (timer_t) new_timer_id; |
@@ -639,6 +637,13 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) | |||
639 | { | 637 | { |
640 | struct k_itimer *timr; | 638 | struct k_itimer *timr; |
641 | 639 | ||
640 | /* | ||
641 | * timer_t could be any type >= int and we want to make sure any | ||
642 | * @timer_id outside positive int range fails lookup. | ||
643 | */ | ||
644 | if ((unsigned long long)timer_id > INT_MAX) | ||
645 | return NULL; | ||
646 | |||
642 | rcu_read_lock(); | 647 | rcu_read_lock(); |
643 | timr = idr_find(&posix_timers_id, (int)timer_id); | 648 | timr = idr_find(&posix_timers_id, (int)timer_id); |
644 | if (timr) { | 649 | if (timr) { |
@@ -997,7 +1002,7 @@ SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock, | |||
997 | 1002 | ||
998 | err = kc->clock_adj(which_clock, &ktx); | 1003 | err = kc->clock_adj(which_clock, &ktx); |
999 | 1004 | ||
1000 | if (!err && copy_to_user(utx, &ktx, sizeof(ktx))) | 1005 | if (err >= 0 && copy_to_user(utx, &ktx, sizeof(ktx))) |
1001 | return -EFAULT; | 1006 | return -EFAULT; |
1002 | 1007 | ||
1003 | return err; | 1008 | return err; |