diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2018-08-02 16:56:48 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2018-08-02 16:56:48 -0400 |
commit | adbfcb32a56177575853583c2bdba42ddb104374 (patch) | |
tree | ef6cfb7734e6370ff8e6239c67a272d3b65b5be7 | |
parent | 5c7695d8103b5933a442fca623c7c18806aafa35 (diff) | |
download | longterm-queue-4.12-adbfcb32a56177575853583c2bdba42ddb104374.tar.gz |
timer: add posix init value patch
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r-- | queue/posix-timer-Properly-check-sigevent-sigev_notify.patch | 111 | ||||
-rw-r--r-- | queue/series | 1 |
2 files changed, 112 insertions, 0 deletions
diff --git a/queue/posix-timer-Properly-check-sigevent-sigev_notify.patch b/queue/posix-timer-Properly-check-sigevent-sigev_notify.patch new file mode 100644 index 0000000..5f33204 --- /dev/null +++ b/queue/posix-timer-Properly-check-sigevent-sigev_notify.patch @@ -0,0 +1,111 @@ +From c6e7a297bffa2b2b1b4117947bb87afdd9819d26 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Fri, 15 Dec 2017 10:32:03 +0100 +Subject: [PATCH] posix-timer: Properly check sigevent->sigev_notify + +commit cef31d9af908243421258f1df35a4a644604efbe upstream. + +timer_create() specifies via sigevent->sigev_notify the signal delivery for +the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD +and (SIGEV_SIGNAL | SIGEV_THREAD_ID). + +The sanity check in good_sigevent() is only checking the valid combination +for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is +not set it accepts any random value. + +This has no real effects on the posix timer and signal delivery code, but +it affects show_timer() which handles the output of /proc/$PID/timers. That +function uses a string array to pretty print sigev_notify. The access to +that array has no bound checks, so random sigev_notify cause access beyond +the array bounds. + +Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID +masking from various code pathes as SIGEV_NONE can never be set in +combination with SIGEV_THREAD_ID. + +Reported-by: Eric Biggers <ebiggers3@gmail.com> +Reported-by: Dmitry Vyukov <dvyukov@google.com> +Reported-by: Alexey Dobriyan <adobriyan@gmail.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: John Stultz <john.stultz@linaro.org> +Cc: stable@vger.kernel.org +[PG: adapt to older code base via inspection of 4.9.x stable.] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c +index 4d7b2ce09c27..e384489aea28 100644 +--- a/kernel/time/posix-timers.c ++++ b/kernel/time/posix-timers.c +@@ -508,17 +508,22 @@ static struct pid *good_sigevent(sigevent_t * event) + { + struct task_struct *rtn = current->group_leader; + +- if ((event->sigev_notify & SIGEV_THREAD_ID ) && +- (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) || +- !same_thread_group(rtn, current) || +- (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) ++ switch (event->sigev_notify) { ++ case SIGEV_SIGNAL | SIGEV_THREAD_ID: ++ rtn = find_task_by_vpid(event->sigev_notify_thread_id); ++ if (!rtn || !same_thread_group(rtn, current)) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_SIGNAL: ++ case SIGEV_THREAD: ++ if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) ++ return NULL; ++ /* FALLTHRU */ ++ case SIGEV_NONE: ++ return task_pid(rtn); ++ default: + return NULL; +- +- if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) && +- ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) +- return NULL; +- +- return task_pid(rtn); ++ } + } + + void posix_timers_register_clock(const clockid_t clock_id, +@@ -746,8 +751,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) + /* interval timer ? */ + if (iv) + cur_setting->it_interval = ktime_to_timespec64(iv); +- else if (!hrtimer_active(timer) && +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE) + return; + + now = timer->base->get_time(); +@@ -758,7 +762,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) + * expiry is > now. + */ + if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || +- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) ++ timr->it_sigev_notify == SIGEV_NONE)) + timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); + + remaining = __hrtimer_expires_remaining_adjusted(timer, now); +@@ -768,7 +772,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) + * A single shot SIGEV_NONE timer must return 0, when + * it is expired ! + */ +- if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) ++ if (timr->it_sigev_notify != SIGEV_NONE) + cur_setting->it_value.tv_nsec = 1; + } else + cur_setting->it_value = ktime_to_timespec64(remaining); +@@ -868,7 +872,7 @@ common_timer_set(struct k_itimer *timr, int flags, + timr->it.real.interval = timespec64_to_ktime(new_setting->it_interval); + + /* SIGEV_NONE timers are not queued ! See common_timer_get */ +- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { ++ if (timr->it_sigev_notify == SIGEV_NONE) { + /* Setup correct expiry time for relative timers */ + if (mode == HRTIMER_MODE_REL) { + hrtimer_add_expires(timer, timer->base->get_time()); +-- +2.15.0 + diff --git a/queue/series b/queue/series index 7c51135..3885604 100644 --- a/queue/series +++ b/queue/series @@ -1,5 +1,6 @@ ACPI-APEI-adjust-a-local-variable-type-in-ghes_iorem.patch x86-platform-UV-Convert-timers-to-use-timer_setup.patch +posix-timer-Properly-check-sigevent-sigev_notify.patch optee-fix-invalid-of_node_put-in-optee_driver_init.patch backlight-pwm_bl-Fix-overflow-condition.patch drm-Add-retries-for-lspcon-mode-detection.patch |