summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Wellving <andreas.wellving@enea.com>2018-10-12 09:28:42 +0200
committerAndreas Wellving <andreas.wellving@enea.com>2018-10-12 09:28:42 +0200
commit307a37fe48bfc9ce3297526b6d6e7d1bf1758448 (patch)
tree5cc3e682cb01bd18ab146699a43577c4ecdadf35
parentbbbaee9150a62c2965710ff2245b65da32f35eb5 (diff)
downloadenea-kernel-cache-307a37fe48bfc9ce3297526b6d6e7d1bf1758448.tar.gz
posix-timer: CVE-2017-18344
posix-timer: Properly check sigevent->sigev_notify References: https://github.com/torvalds/linux/commit/cef31d9af908243421258f1df35a4a644604efbe Change-Id: I1cea661130c10f10cc2b3ffc480fff9d8ed3ee0e Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
-rw-r--r--patches/cve/4.9.x.scc2
-rw-r--r--patches/cve/CVE-2017-18344-posix-timer-Properly-check-sigevent-sigev_notify.patch113
2 files changed, 115 insertions, 0 deletions
diff --git a/patches/cve/4.9.x.scc b/patches/cve/4.9.x.scc
new file mode 100644
index 0000000..4fa6185
--- /dev/null
+++ b/patches/cve/4.9.x.scc
@@ -0,0 +1,2 @@
1#CVEs fixed in 4.9.82:
2patch CVE-2017-18344-posix-timer-Properly-check-sigevent-sigev_notify.patch
diff --git a/patches/cve/CVE-2017-18344-posix-timer-Properly-check-sigevent-sigev_notify.patch b/patches/cve/CVE-2017-18344-posix-timer-Properly-check-sigevent-sigev_notify.patch
new file mode 100644
index 0000000..ebab261
--- /dev/null
+++ b/patches/cve/CVE-2017-18344-posix-timer-Properly-check-sigevent-sigev_notify.patch
@@ -0,0 +1,113 @@
1Date: Thu, 11 Oct 2018 15:28:37 +0200
2Subject: [PATCH] posix-timer: Properly check sigevent->sigev_notify
3
4commit cef31d9af908243421258f1df35a4a644604efbe upstream.
5
6timer_create() specifies via sigevent->sigev_notify the signal delivery for
7the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD
8and (SIGEV_SIGNAL | SIGEV_THREAD_ID).
9
10The sanity check in good_sigevent() is only checking the valid combination
11for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is
12not set it accepts any random value.
13
14This has no real effects on the posix timer and signal delivery code, but
15it affects show_timer() which handles the output of /proc/$PID/timers. That
16function uses a string array to pretty print sigev_notify. The access to
17that array has no bound checks, so random sigev_notify cause access beyond
18the array bounds.
19
20Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID
21masking from various code pathes as SIGEV_NONE can never be set in
22combination with SIGEV_THREAD_ID.
23
24CVE: CVE-2017-18344
25Upstream-Status: Backport
26
27Reported-by: Eric Biggers <ebiggers3@gmail.com>
28Reported-by: Dmitry Vyukov <dvyukov@google.com>
29Reported-by: Alexey Dobriyan <adobriyan@gmail.com>
30Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
31Cc: John Stultz <john.stultz@linaro.org>
32Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
34---
35 kernel/time/posix-timers.c | 33 +++++++++++++++++++--------------
36 1 file changed, 19 insertions(+), 14 deletions(-)
37
38diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
39index f2826c3..72c40d3 100644
40--- a/kernel/time/posix-timers.c
41+++ b/kernel/time/posix-timers.c
42@@ -507,17 +507,22 @@ static struct pid *good_sigevent(sigevent_t * event)
43 {
44 struct task_struct *rtn = current->group_leader;
45
46- if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
47- (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
48- !same_thread_group(rtn, current) ||
49- (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
50+ switch (event->sigev_notify) {
51+ case SIGEV_SIGNAL | SIGEV_THREAD_ID:
52+ rtn = find_task_by_vpid(event->sigev_notify_thread_id);
53+ if (!rtn || !same_thread_group(rtn, current))
54+ return NULL;
55+ /* FALLTHRU */
56+ case SIGEV_SIGNAL:
57+ case SIGEV_THREAD:
58+ if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
59+ return NULL;
60+ /* FALLTHRU */
61+ case SIGEV_NONE:
62+ return task_pid(rtn);
63+ default:
64 return NULL;
65-
66- if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
67- ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX)))
68- return NULL;
69-
70- return task_pid(rtn);
71+ }
72 }
73
74 void posix_timers_register_clock(const clockid_t clock_id,
75@@ -746,7 +751,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
76 if (iv.tv64)
77 cur_setting->it_interval = ktime_to_timespec(iv);
78 else if (!hrtimer_active(timer) &&
79- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
80+ timr->it_sigev_notify != SIGEV_NONE)
81 return;
82
83 now = timer->base->get_time();
84@@ -757,7 +762,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
85 * expiry is > now.
86 */
87 if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
88- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
89+ timr->it_sigev_notify == SIGEV_NONE))
90 timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
91
92 remaining = __hrtimer_expires_remaining_adjusted(timer, now);
93@@ -767,7 +772,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
94 * A single shot SIGEV_NONE timer must return 0, when
95 * it is expired !
96 */
97- if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
98+ if (timr->it_sigev_notify != SIGEV_NONE)
99 cur_setting->it_value.tv_nsec = 1;
100 } else
101 cur_setting->it_value = ktime_to_timespec(remaining);
102@@ -865,7 +870,7 @@ common_timer_set(struct k_itimer *timr, int flags,
103 timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
104
105 /* SIGEV_NONE timers are not queued ! See common_timer_get */
106- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
107+ if (timr->it_sigev_notify == SIGEV_NONE) {
108 /* Setup correct expiry time for relative timers */
109 if (mode == HRTIMER_MODE_REL) {
110 hrtimer_add_expires(timer, timer->base->get_time());
111--
112
113