Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2002586imu; Fri, 14 Dec 2018 04:20:04 -0800 (PST) X-Google-Smtp-Source: AFSGD/UAnTZJ/QOazQ9r/CiV+y88tfeLT0H+r1A5AnagG2DUCevHAAx6oNtHipuZVFIATvs2+mxY X-Received: by 2002:a62:6385:: with SMTP id x127mr2655295pfb.15.1544790004132; Fri, 14 Dec 2018 04:20:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544790004; cv=none; d=google.com; s=arc-20160816; b=TCQdO43CpzsC+cRu54KicpKFVUxKiAfyvoWgDCqXQy1VxZNqFOBIMHY2mYmHXMbBRz wWmgzcyoSQ7bRb+tgpAXv3Yq7Vyq802riMP1cICtUIli6lyaqg6H5v4nLmSE/zPLfATL WeskbVhWq387mcxscxpPKKv9++DoKqyaSdhNgLrZwIhogUr54hy+0kAe47rVJbgrK/V9 XvXs4FDHtHimrnMEwnyMZxU79kqW1GYlM3rSs/Eo0cCngo2dchA/cbE61NPBdIceYfph eBh8XbksRFVpag+vQU32ig+b/AzeIb4y/lZTjMtoj1pG+5BOKwvxG8hN2IGQeP60umvU 44fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=AYUNJZNUZv3ANPEGyef7lGO9ghk0kJIM0z0ecE7Ctow=; b=rYAWViNPK+IEn9lGktpNpsdbGNROPWglleKjokPNKDdNhyGqGx3RFXSNw7foWHetYe tehX4c0SA+8uP6RFIwWw72CealkqUnOZZErnMOPX8ozgnpzvaCstFQGZjKSQvLB6oZps TRIOeJGKKUNNS9eybu3rYboNmTuWk6hOdwzcLZWVTCLo9BOcF5QC3aNMAi8oWP1UOMeu YarDTK0d8MXn/2swLCbIo+aO4sbtlOuLDsQPdTY2NQ33/CW5stsrBEkLh40F4vh6P0M8 HIM27uG+A+FsB+bDKKCoJHZTlzodUSRaORujfyouGirft0YzCyt0sxfEyfWv+V9tYQJQ Kz7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=PisO1XSk; 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 x74si4286085pfe.23.2018.12.14.04.19.49; Fri, 14 Dec 2018 04:20:04 -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; dkim=pass header.i=@kernel.org header.s=default header.b=PisO1XSk; 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 S1732691AbeLNMQI (ORCPT + 99 others); Fri, 14 Dec 2018 07:16:08 -0500 Received: from mail.kernel.org ([198.145.29.99]:36132 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732402AbeLNMQC (ORCPT ); Fri, 14 Dec 2018 07:16:02 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 5AC44214C1; Fri, 14 Dec 2018 12:16:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1544789760; bh=fq5KOfcSjRR6O63TyJHg8rZKAkGwaE5S2GXDunqz94E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PisO1XSkeyDm7/zxQVIdcJEiVReRSEgWldDjeKNyvc82AdpRHsEU/Yw1+MHsirx25 hoTnaZdktQyjnr/kSFYLj62EWyjFZa+NjgfdH0xreGG4Qh0b9xxzLacI2nEDgLn0Tq fhNAZ7jmenJKjGNU/4YRABTQJbhu/AyaGv0/EET0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Team OWL337 , Thomas Gleixner , John Stultz , Peter Zijlstra , Michael Kerrisk , Florian Fainelli , Sasha Levin , Ben Hutchings Subject: [PATCH 4.4 67/88] posix-timers: Sanitize overrun handling Date: Fri, 14 Dec 2018 13:00:41 +0100 Message-Id: <20181214115707.827988053@linuxfoundation.org> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181214115702.151309521@linuxfoundation.org> References: <20181214115702.151309521@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Thomas Gleixner commit 78c9c4dfbf8c04883941445a195276bb4bb92c76 upstream. The posix timer overrun handling is broken because the forwarding functions can return a huge number of overruns which does not fit in an int. As a consequence timer_getoverrun(2) and siginfo::si_overrun can turn into random number generators. The k_clock::timer_forward() callbacks return a 64 bit value now. Make k_itimer::ti_overrun[_last] 64bit as well, so the kernel internal accounting is correct. 3Remove the temporary (int) casts. Add a helper function which clamps the overrun value returned to user space via timer_getoverrun(2) or siginfo::si_overrun limited to a positive value between 0 and INT_MAX. INT_MAX is an indicator for user space that the overrun value has been clamped. Reported-by: Team OWL337 Signed-off-by: Thomas Gleixner Acked-by: John Stultz Cc: Peter Zijlstra Cc: Michael Kerrisk Link: https://lkml.kernel.org/r/20180626132705.018623573@linutronix.de [florian: Make patch apply to v4.9.135] Signed-off-by: Florian Fainelli Reviewed-by: Thomas Gleixner Signed-off-by: Sasha Levin Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- include/linux/posix-timers.h | 4 ++-- kernel/time/posix-cpu-timers.c | 2 +- kernel/time/posix-timers.c | 29 +++++++++++++++++++---------- 3 files changed, 22 insertions(+), 13 deletions(-) --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -65,8 +65,8 @@ struct k_itimer { spinlock_t it_lock; clockid_t it_clock; /* which timer type */ timer_t it_id; /* timer id */ - int it_overrun; /* overrun on pending signal */ - int it_overrun_last; /* overrun on last delivered signal */ + s64 it_overrun; /* overrun on pending signal */ + s64 it_overrun_last; /* overrun on last delivered signal */ int it_requeue_pending; /* waiting to requeue this timer */ #define REQUEUE_PENDING 1 int it_sigev_notify; /* notify word of sigevent struct */ --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -103,7 +103,7 @@ static void bump_cpu_timer(struct k_itim continue; timer->it.cpu.expires += incr; - timer->it_overrun += 1 << i; + timer->it_overrun += 1LL << i; delta -= incr; } } --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -355,6 +355,17 @@ static __init int init_posix_timers(void __initcall(init_posix_timers); +/* + * The siginfo si_overrun field and the return value of timer_getoverrun(2) + * are of type int. Clamp the overrun value to INT_MAX + */ +static inline int timer_overrun_to_int(struct k_itimer *timr, int baseval) +{ + s64 sum = timr->it_overrun_last + (s64)baseval; + + return sum > (s64)INT_MAX ? INT_MAX : (int)sum; +} + static void schedule_next_timer(struct k_itimer *timr) { struct hrtimer *timer = &timr->it.real.timer; @@ -362,12 +373,11 @@ static void schedule_next_timer(struct k if (timr->it.real.interval.tv64 == 0) return; - timr->it_overrun += (unsigned int) hrtimer_forward(timer, - timer->base->get_time(), - timr->it.real.interval); + timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(), + timr->it.real.interval); timr->it_overrun_last = timr->it_overrun; - timr->it_overrun = -1; + timr->it_overrun = -1LL; ++timr->it_requeue_pending; hrtimer_restart(timer); } @@ -396,7 +406,7 @@ void do_schedule_next_timer(struct sigin else schedule_next_timer(timr); - info->si_overrun += timr->it_overrun_last; + info->si_overrun = timer_overrun_to_int(timr, info->si_overrun); } if (timr) @@ -491,8 +501,7 @@ static enum hrtimer_restart posix_timer_ now = ktime_add(now, kj); } #endif - timr->it_overrun += (unsigned int) - hrtimer_forward(timer, now, + timr->it_overrun += hrtimer_forward(timer, now, timr->it.real.interval); ret = HRTIMER_RESTART; ++timr->it_requeue_pending; @@ -633,7 +642,7 @@ SYSCALL_DEFINE3(timer_create, const cloc it_id_set = IT_ID_SET; new_timer->it_id = (timer_t) new_timer_id; new_timer->it_clock = which_clock; - new_timer->it_overrun = -1; + new_timer->it_overrun = -1LL; if (timer_event_spec) { if (copy_from_user(&event, timer_event_spec, sizeof (event))) { @@ -762,7 +771,7 @@ common_timer_get(struct k_itimer *timr, */ if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING || timr->it_sigev_notify == SIGEV_NONE)) - timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); + timr->it_overrun += hrtimer_forward(timer, now, iv); remaining = __hrtimer_expires_remaining_adjusted(timer, now); /* Return 0 only, when the timer is expired and not pending */ @@ -824,7 +833,7 @@ SYSCALL_DEFINE1(timer_getoverrun, timer_ if (!timr) return -EINVAL; - overrun = timr->it_overrun_last; + overrun = timer_overrun_to_int(timr, 0); unlock_timer(timr, flags); return overrun;