From patchwork Tue Apr 4 22:12:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9662711 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 02E0F6032D for ; Tue, 4 Apr 2017 22:13:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8EEB27F94 for ; Tue, 4 Apr 2017 22:13:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DDAF528587; Tue, 4 Apr 2017 22:13:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 13C7627F94 for ; Tue, 4 Apr 2017 22:13:27 +0000 (UTC) Received: (qmail 26483 invoked by uid 550); 4 Apr 2017 22:12:42 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 26319 invoked from network); 4 Apr 2017 22:12:39 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=I67YypH7AL0Dr/IkGvSmFImnhY9B9J9xjruLyAuSPHI=; b=WSTmDrSjOpgr+yGDwb3xLJKccxt5jXeiw+wYsW4JAQy7lka0P0SgjAXTz4W35Jp5s/ /Cnii6g1Jywv4apAOYQpCvTmR9JrrIrrxjVv+d2RCJvZI6PMSPIaTU13p844xm+gvpCF P4v+BDBRGuPM0hFx7jz7MuP7HH+ZUshf1p/IY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=I67YypH7AL0Dr/IkGvSmFImnhY9B9J9xjruLyAuSPHI=; b=r4MI9GoDXDDKSTHf9BVwsF4sfegRZQOxC75eu7g8yBonhRaJn98/KtRS4D1CtVC2A/ bQXKmXX2puiTfHo5ZntD49nBPJtgchQxMeHAzmNkwvf5wNSZc1qVRO/I7vp9W8HQyeU4 EJwbf0mpticUuR7Ym3aQJXp5rdnejgy94OEjqt9Ep72JsfXblcrLak8af2CtaOZEION/ dNJW5+A0MKsexV51rTwY9royMqasTqrvuahjYFCbrKJcFjESIhZfEEdvuCUktGZy3bXj A1MO0Ef/m0Q4WlRZ6M5FSCe93sA/OZqzbQcVtizs0ca266KmtEkCx5DmXeHgyhjqijf2 LHbQ== X-Gm-Message-State: AFeK/H2vILEymWzmlFYeXvBWr56CZjMve6cc9Wt8p2Dfnf/fmvqYQDQSra5qULQxUHFdQPFw X-Received: by 10.98.150.75 with SMTP id c72mr25093499pfe.106.1491343947425; Tue, 04 Apr 2017 15:12:27 -0700 (PDT) From: Kees Cook To: Ingo Molnar Cc: Kees Cook , Peter Zijlstra , "Paul E. McKenney" , Kalle Valo , Andrew Morton , Rik van Riel , Jakub Kicinski , Viresh Kumar , Andy Shevchenko , Geert Uytterhoeven , Olof Johansson , Chris Wilson , George Spelvin , Thomas Gleixner , Josh Poimboeuf , David Windsor , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com Date: Tue, 4 Apr 2017 15:12:18 -0700 Message-Id: <1491343938-75336-8-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491343938-75336-1-git-send-email-keescook@chromium.org> References: <1491343938-75336-1-git-send-email-keescook@chromium.org> Subject: [kernel-hardening] [PATCH v2 7/7] refcount: Check bad states with CHECK_DATA_CORRUPTION() X-Virus-Scanned: ClamAV using ClamSMTP This converts from WARN_ONCE() to CHECK_DATA_CORRUPTION() (so that system builders can choose between WARN and BUG). Additionally moves refcount_t sanity-check conditionals into regular function flow. Now when built with CONFIG_BUG_ON_DATA_CORRUPTION, the LKDTM REFCOUNT_* tests correctly kill offending processes. Signed-off-by: Kees Cook --- lib/refcount.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/refcount.c b/lib/refcount.c index f42124ccf295..88289210d9fd 100644 --- a/lib/refcount.c +++ b/lib/refcount.c @@ -37,6 +37,13 @@ #include #include +/* + * CHECK_DATA_CORRUPTION() is defined with __must_check, but we have a + * couple places where we want to report a condition that has already + * been checked, so this lets us cheat __must_check. + */ +#define REFCOUNT_CHECK(cond, str) unlikely(CHECK_DATA_CORRUPTION(cond, str)) + /** * refcount_add_not_zero - add a value to a refcount unless it is 0 * @i: the value to add to the refcount @@ -72,7 +79,8 @@ bool refcount_add_not_zero(unsigned int i, refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); - WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); + REFCOUNT_CHECK(new == UINT_MAX, + "refcount_t: add saturated; leaking memory.\n"); return true; } @@ -96,7 +104,8 @@ EXPORT_SYMBOL_GPL(refcount_add_not_zero); */ void refcount_add(unsigned int i, refcount_t *r) { - WARN_ONCE(!refcount_add_not_zero(i, r), "refcount_t: addition on 0; use-after-free.\n"); + REFCOUNT_CHECK(!refcount_add_not_zero(i, r), + "refcount_t: addition on 0; use-after-free.\n"); } EXPORT_SYMBOL_GPL(refcount_add); @@ -127,7 +136,8 @@ bool refcount_inc_not_zero(refcount_t *r) } while (!atomic_try_cmpxchg_relaxed(&r->refs, &val, new)); - WARN_ONCE(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n"); + REFCOUNT_CHECK(new == UINT_MAX, + "refcount_t: inc saturated; leaking memory.\n"); return true; } @@ -147,7 +157,8 @@ EXPORT_SYMBOL_GPL(refcount_inc_not_zero); */ void refcount_inc(refcount_t *r) { - WARN_ONCE(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n"); + REFCOUNT_CHECK(!refcount_inc_not_zero(r), + "refcount_t: increment on 0; use-after-free.\n"); } EXPORT_SYMBOL_GPL(refcount_inc); @@ -180,10 +191,9 @@ bool refcount_sub_and_test(unsigned int i, refcount_t *r) return false; new = val - i; - if (new > val) { - WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); + if (REFCOUNT_CHECK(new > val, + "refcount_t: sub underflow; use-after-free.\n")) return false; - } } while (!atomic_try_cmpxchg_release(&r->refs, &val, new)); @@ -222,7 +232,8 @@ EXPORT_SYMBOL_GPL(refcount_dec_and_test); */ void refcount_dec(refcount_t *r) { - WARN_ONCE(refcount_dec_and_test(r), "refcount_t: decrement hit 0; leaking memory.\n"); + REFCOUNT_CHECK(refcount_dec_and_test(r), + "refcount_t: decrement hit 0; leaking memory.\n"); } EXPORT_SYMBOL_GPL(refcount_dec); @@ -273,10 +284,9 @@ bool refcount_dec_not_one(refcount_t *r) return false; new = val - 1; - if (new > val) { - WARN_ONCE(new > val, "refcount_t: underflow; use-after-free.\n"); + if (REFCOUNT_CHECK(new > val, + "refcount_t: dec underflow; use-after-free.\n")) return true; - } } while (!atomic_try_cmpxchg_release(&r->refs, &val, new)); @@ -345,4 +355,3 @@ bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) return true; } EXPORT_SYMBOL_GPL(refcount_dec_and_lock); -