From 6812610424262b90d3e5635291b1e4933cf8bd89 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Feb 2018 17:21:55 +0100 Subject: [PATCH] posix-timers: Protect posix clock array access against speculation commit 19b558db12f9f4e45a22012bae7b4783e62224da upstream. The clockid argument of clockid_to_kclock() comes straight from user space via various syscalls and is used as index into the posix_clocks array. Protect it against spectre v1 array out of bounds speculation. Remove the redundant check for !posix_clock[id] as this is another source for speculation and does not provide any advantage over the return posix_clock[id] path which returns NULL in that case anyway. Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra (Intel) Acked-by: Dan Williams Cc: Rasmus Villemoes Cc: Greg KH Cc: Linus Torvalds Cc: David Woodhouse Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1802151718320.1296@nanos.tec.linutronix.de [bwh: Backported to 3.2: - Move the test of the clock_getres field below the lookup using array_index_nospec() - Adjust filename, context] Signed-off-by: Ben Hutchings --- kernel/posix-timers.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 4a32f9cd96dc..3130973c2d13 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -47,6 +47,7 @@ #include #include #include +#include /* * Management arrays for POSIX timers. Timers are kept in slab memory @@ -520,13 +521,21 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) static struct k_clock *clockid_to_kclock(const clockid_t id) { - if (id < 0) + clockid_t idx = id; + struct k_clock *kc; + + if (id < 0) { return (id & CLOCKFD_MASK) == CLOCKFD ? &clock_posix_dynamic : &clock_posix_cpu; + } + + if (id >= ARRAY_SIZE(posix_clocks)) + return NULL; - if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres) + kc = &posix_clocks[array_index_nospec(idx, ARRAY_SIZE(posix_clocks))]; + if (!kc->clock_getres) return NULL; - return &posix_clocks[id]; + return kc; } static int common_timer_create(struct k_itimer *new_timer) -- 2.39.2