summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Gortmaker <paul.gortmaker@windriver.com>2018-08-02 16:56:48 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2018-08-02 16:56:48 -0400
commitadbfcb32a56177575853583c2bdba42ddb104374 (patch)
treeef6cfb7734e6370ff8e6239c67a272d3b65b5be7
parent5c7695d8103b5933a442fca623c7c18806aafa35 (diff)
downloadlongterm-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.patch111
-rw-r--r--queue/series1
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