Received: by 10.223.185.116 with SMTP id b49csp6384218wrg; Wed, 28 Feb 2018 08:31:38 -0800 (PST) X-Google-Smtp-Source: AH8x2271nKVHWvokkMi7GT5tuVU7/xiNJyuC7Am4aTV2O7iTIA4Jztus+fqepYAa7U2m+wbYs8Lu X-Received: by 10.98.61.73 with SMTP id k70mr18416184pfa.10.1519835498572; Wed, 28 Feb 2018 08:31:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519835498; cv=none; d=google.com; s=arc-20160816; b=E4Un7MvSHheqa6zpvj+kFG+wCGHK1YKavbgmJA0jvKm3cRdThsVfmKn1CJvZs8FWpo dT9g1zOfwnfwyuHTr3703dO1MNGnwEwlZnc3Ted7bJW0KlQqnUuJ1eygIncC8AVpClSS TCFy8cEqhWqeemZWbtfxXZw8nWmiEr3tb6T5ObkawN3R5FyijAisPDyoP+Oo9xPXZYX0 LlrzzJHJUSJRWb2iHQ1RzRLW31k3ir/7nw0vfz1hmIHxudrN+1YD5tANmHTMRPl062me HkQ3bwsGX36HmaNRmyTh3dPHV2VENRpANgUspCllOjF4f/YQ4E0MHfljBGX05NBl7LTS 2KNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition :arc-authentication-results; bh=SpcvM7+QXrPRo7sNcIX4M2vkB9ELa0Ky08I8femJifE=; b=mxvgT/6jcPdZOcvDkWr39FHtCXP6t5BgqpKzCpXwS+wjBj47VDvdE1zk8j3Elh+nO0 ukLC4o5YyOMTqJFF9ulNnoRuyv7VTHzcUwzj8GPHu0k6vqy4z3KmXvfYwS/kU7F2GPQB +B4oSXiW9iThqJkeTLa6AR5BWmKV+/iT/od5GKtpO/PWEM+ibBNXe2i2wPFJKgVCrvL6 vhpZLIB10ORAE74BmtaRengvBsa5Znwk8pMslHjuuP+gdSexbE3kLweCNxukp2vYhBVb 7EPf8nGCHBOnGFsKh65CvyMUqAlibC/4ODxfM1JOLf1Oac4E4OOvXHcQbeCatuGjwCB4 Bm+w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m10-v6si1535949pll.436.2018.02.28.08.31.24; Wed, 28 Feb 2018 08:31:38 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934584AbeB1Qa1 (ORCPT + 99 others); Wed, 28 Feb 2018 11:30:27 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:35158 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934625AbeB1QPK (ORCPT ); Wed, 28 Feb 2018 11:15:10 -0500 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1er3Yi-0006XS-FG; Wed, 28 Feb 2018 15:22:20 +0000 Received: from ben by deadeye with local (Exim 4.90_1) (envelope-from ) id 1er3Yg-00006J-Pd; Wed, 28 Feb 2018 15:22:18 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "John Stultz" , "Eric Biggers" , "Alexey Dobriyan" , "Thomas Gleixner" , "Dmitry Vyukov" Date: Wed, 28 Feb 2018 15:20:18 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 117/254] posix-timer: Properly check sigevent->sigev_notify In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.55-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Thomas Gleixner 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 Reported-by: Dmitry Vyukov Reported-by: Alexey Dobriyan Signed-off-by: Thomas Gleixner Cc: John Stultz [bwh: Backported to 3.16: - Add sig_none variable in common_timer_get(), added earlier upstream - Adjust filename, context] Signed-off-by: Ben Hutchings --- kernel/posix-timers.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -498,17 +498,22 @@ static struct pid *good_sigevent(sigeven { 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, @@ -728,16 +733,17 @@ common_timer_get(struct k_itimer *timr, { ktime_t now, remaining, iv; struct hrtimer *timer = &timr->it.real.timer; + bool sig_none; memset(cur_setting, 0, sizeof(struct itimerspec)); + sig_none = timr->it_sigev_notify == SIGEV_NONE; iv = timr->it.real.interval; /* interval timer ? */ if (iv.tv64) cur_setting->it_interval = ktime_to_timespec(iv); - else if (!hrtimer_active(timer) && - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) + else if (!hrtimer_active(timer) && !sig_none) return; now = timer->base->get_time(); @@ -747,8 +753,7 @@ common_timer_get(struct k_itimer *timr, * timer move the expiry time forward by intervals, so * expiry is > now. */ - if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || - (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) + if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none)) timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); remaining = ktime_sub(hrtimer_get_expires(timer), now); @@ -758,7 +763,7 @@ common_timer_get(struct k_itimer *timr, * A single shot SIGEV_NONE timer must return 0, when * it is expired ! */ - if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) + if (!sig_none) cur_setting->it_value.tv_nsec = 1; } else cur_setting->it_value = ktime_to_timespec(remaining); @@ -856,7 +861,7 @@ common_timer_set(struct k_itimer *timr, timr->it.real.interval = timespec_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());