diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-17 16:48:50 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-12-17 16:48:50 -0500 |
| commit | 2ffb448ccbdd3de16e68220d4fa0864a75272dc3 (patch) | |
| tree | 5c558844757b6f511e41a3d81dafb04dcb184157 | |
| parent | c43727908f5589970d954e995a6cb0dcff837dcd (diff) | |
| parent | cef31d9af908243421258f1df35a4a644604efbe (diff) | |
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fix from Thomas Gleixner:
"A single bugfix which prevents arbitrary sigev_notify values in
posix-timers"
* 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
posix-timer: Properly check sigevent->sigev_notify
| -rw-r--r-- | kernel/time/posix-timers.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 13d6881f908b..ec999f32c840 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
| @@ -434,17 +434,22 @@ static struct pid *good_sigevent(sigevent_t * event) | |||
| 434 | { | 434 | { |
| 435 | struct task_struct *rtn = current->group_leader; | 435 | struct task_struct *rtn = current->group_leader; |
| 436 | 436 | ||
| 437 | if ((event->sigev_notify & SIGEV_THREAD_ID ) && | 437 | switch (event->sigev_notify) { |
| 438 | (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) || | 438 | case SIGEV_SIGNAL | SIGEV_THREAD_ID: |
| 439 | !same_thread_group(rtn, current) || | 439 | rtn = find_task_by_vpid(event->sigev_notify_thread_id); |
| 440 | (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) | 440 | if (!rtn || !same_thread_group(rtn, current)) |
| 441 | return NULL; | ||
| 442 | /* FALLTHRU */ | ||
| 443 | case SIGEV_SIGNAL: | ||
| 444 | case SIGEV_THREAD: | ||
| 445 | if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) | ||
| 446 | return NULL; | ||
| 447 | /* FALLTHRU */ | ||
| 448 | case SIGEV_NONE: | ||
| 449 | return task_pid(rtn); | ||
| 450 | default: | ||
| 441 | return NULL; | 451 | return NULL; |
| 442 | 452 | } | |
| 443 | if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) && | ||
| 444 | ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) | ||
| 445 | return NULL; | ||
| 446 | |||
| 447 | return task_pid(rtn); | ||
| 448 | } | 453 | } |
| 449 | 454 | ||
| 450 | static struct k_itimer * alloc_posix_timer(void) | 455 | static struct k_itimer * alloc_posix_timer(void) |
| @@ -669,7 +674,7 @@ void common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) | |||
| 669 | struct timespec64 ts64; | 674 | struct timespec64 ts64; |
| 670 | bool sig_none; | 675 | bool sig_none; |
| 671 | 676 | ||
| 672 | sig_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE; | 677 | sig_none = timr->it_sigev_notify == SIGEV_NONE; |
| 673 | iv = timr->it_interval; | 678 | iv = timr->it_interval; |
| 674 | 679 | ||
| 675 | /* interval timer ? */ | 680 | /* interval timer ? */ |
| @@ -856,7 +861,7 @@ int common_timer_set(struct k_itimer *timr, int flags, | |||
| 856 | 861 | ||
| 857 | timr->it_interval = timespec64_to_ktime(new_setting->it_interval); | 862 | timr->it_interval = timespec64_to_ktime(new_setting->it_interval); |
| 858 | expires = timespec64_to_ktime(new_setting->it_value); | 863 | expires = timespec64_to_ktime(new_setting->it_value); |
| 859 | sigev_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE; | 864 | sigev_none = timr->it_sigev_notify == SIGEV_NONE; |
| 860 | 865 | ||
| 861 | kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); | 866 | kc->timer_arm(timr, expires, flags & TIMER_ABSTIME, sigev_none); |
| 862 | timr->it_active = !sigev_none; | 867 | timr->it_active = !sigev_none; |
