Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp2583636ybc; Mon, 25 Nov 2019 00:23:56 -0800 (PST) X-Google-Smtp-Source: APXvYqwKos8im89f8P2DzBT7MWrDnGVjxv9+YvOqfhBNS2rUs14OjdqEPqbQ0EoM3vsvDrWDUnPI X-Received: by 2002:a17:906:d052:: with SMTP id bo18mr36359046ejb.128.1574670236423; Mon, 25 Nov 2019 00:23:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574670236; cv=none; d=google.com; s=arc-20160816; b=TgsVgIu0kbJ7dmNYtqAOZFpsttzob+wOP5pMCo/bpv36qMvGQ3AAnhYPepB2TlBCQ0 /goFqB5xjnmmkRv7EprCPc5Tvx1iBMFHOs1AY98wAfBvy97pdmVizl58wvA9mkXhTzcz dHczRm22M8btyHg5wv/IQt2LiS7NfApFugYRm+4Ii45JVibM61uUA66LdVfuBbsNq2ui AN/sShWwbMfiQZTBBcsmDcyOpNpORFo8OrXB5EmPRHtvQ+QuZDQdabFoKCT4LLX8KQbS zbNT/p3UWHlRvx+6cL1uSzbMQ3n3E4ExofFSbsCR52RYqfcSN6D1v5lpuTIhX6IOkB2R ngew== 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 :robot-unsubscribe:robot-id:message-id:mime-version:references :in-reply-to:cc:subject:to:reply-to:from:date; bh=JOIzBdjuMC0Fm1TEgfdpgabVqWAF2TohYgjjJczgne0=; b=VMZb39EeiCvN5FVenWg1Dvuh6EwbZlHo8Pr2tP6JJEIW13BUxhcmR/aoylM1WKekox CVgl9vvTXxskr9TD+ntir0KCmCZoTPjh8rIJbmHN1zI2lJBM0fFUZ3vRl/wBqKH5Qowc EPkZmqM6l27zOMdL17MFdXwwwbJWSSoEzZG5O7Q/iyHNHPU2tzJA68wPUlS7nkQKqki3 9jb9xjAmsmlNZsauooX9whWDEjjsjQ7QeQSpmR+gn61lSsHmWC0KEL+EHO7XG3VjZwBP pSh4xweJg50qEwDjJSXGZdTH5tHJvP9FRc9mQD/UoYKAesAw7eU8gRWR+bSZW1r8zpTr NUTQ== 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 z43si5055107edb.374.2019.11.25.00.23.32; Mon, 25 Nov 2019 00:23:56 -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 S1727280AbfKYITo (ORCPT + 99 others); Mon, 25 Nov 2019 03:19:44 -0500 Received: from Galois.linutronix.de ([193.142.43.55]:38707 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727165AbfKYIT2 (ORCPT ); Mon, 25 Nov 2019 03:19:28 -0500 Received: from [5.158.153.53] (helo=tip-bot2.lab.linutronix.de) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1iZ9aR-0001QY-Vw; Mon, 25 Nov 2019 09:19:12 +0100 Received: from [127.0.1.1] (localhost [IPv6:::1]) by tip-bot2.lab.linutronix.de (Postfix) with ESMTP id A4EDF1C1AF2; Mon, 25 Nov 2019 09:19:11 +0100 (CET) Date: Mon, 25 Nov 2019 08:19:11 -0000 From: "tip-bot2 for Will Deacon" Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: locking/core] locking/refcount: Move saturation warnings out of line Cc: Will Deacon , Ard Biesheuvel , Kees Cook , Hanjun Guo , Ard Biesheuvel , Elena Reshetova , Linus Torvalds , Peter Zijlstra , Thomas Gleixner , Ingo Molnar , x86 , LKML In-Reply-To: <20191121115902.2551-7-will@kernel.org> References: <20191121115902.2551-7-will@kernel.org> MIME-Version: 1.0 Message-ID: <157466995157.21853.6479453269040766105.tip-bot2@tip-bot2> X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the locking/core branch of tip: Commit-ID: 1eb085d94256aaa69b00cf5a86e3c5f5bb2bc460 Gitweb: https://git.kernel.org/tip/1eb085d94256aaa69b00cf5a86e3c5f5bb2bc460 Author: Will Deacon AuthorDate: Thu, 21 Nov 2019 11:58:58 Committer: Ingo Molnar CommitterDate: Mon, 25 Nov 2019 09:15:21 +01:00 locking/refcount: Move saturation warnings out of line Having the refcount saturation and warnings inline bloats the text, despite the fact that these paths should never be executed in normal operation. Move the refcount saturation and warnings out of line to reduce the image size when refcount_t checking is enabled. Relative to an x86_64 defconfig, the sizes reported by bloat-o-meter are: # defconfig+REFCOUNT_FULL, inline saturation (i.e. before this patch) Total: Before=14762076, After=14915442, chg +1.04% # defconfig+REFCOUNT_FULL, out-of-line saturation (i.e. after this patch) Total: Before=14762076, After=14835497, chg +0.50% A side-effect of this change is that we now only get one warning per refcount saturation type, rather than one per problematic call-site. Signed-off-by: Will Deacon Reviewed-by: Ard Biesheuvel Reviewed-by: Kees Cook Tested-by: Hanjun Guo Cc: Ard Biesheuvel Cc: Elena Reshetova Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: https://lkml.kernel.org/r/20191121115902.2551-7-will@kernel.org Signed-off-by: Ingo Molnar --- include/linux/refcount.h | 39 ++++++++++++++++++++------------------- lib/refcount.c | 28 ++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/include/linux/refcount.h b/include/linux/refcount.h index e3b218d..1cd0a87 100644 --- a/include/linux/refcount.h +++ b/include/linux/refcount.h @@ -23,6 +23,16 @@ typedef struct refcount_struct { #define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } +enum refcount_saturation_type { + REFCOUNT_ADD_NOT_ZERO_OVF, + REFCOUNT_ADD_OVF, + REFCOUNT_ADD_UAF, + REFCOUNT_SUB_UAF, + REFCOUNT_DEC_LEAK, +}; + +void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t); + /** * refcount_set - set a refcount's value * @r: the refcount @@ -154,10 +164,8 @@ static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) break; } while (!atomic_try_cmpxchg_relaxed(&r->refs, &old, old + i)); - if (unlikely(old < 0 || old + i < 0)) { - refcount_set(r, REFCOUNT_SATURATED); - WARN_ONCE(1, "refcount_t: saturated; leaking memory.\n"); - } + if (unlikely(old < 0 || old + i < 0)) + refcount_warn_saturate(r, REFCOUNT_ADD_NOT_ZERO_OVF); return old; } @@ -182,11 +190,10 @@ static inline void refcount_add(int i, refcount_t *r) { int old = atomic_fetch_add_relaxed(i, &r->refs); - WARN_ONCE(!old, "refcount_t: addition on 0; use-after-free.\n"); - if (unlikely(old <= 0 || old + i <= 0)) { - refcount_set(r, REFCOUNT_SATURATED); - WARN_ONCE(old, "refcount_t: saturated; leaking memory.\n"); - } + if (unlikely(!old)) + refcount_warn_saturate(r, REFCOUNT_ADD_UAF); + else if (unlikely(old < 0 || old + i < 0)) + refcount_warn_saturate(r, REFCOUNT_ADD_OVF); } /** @@ -253,10 +260,8 @@ static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r) return true; } - if (unlikely(old < 0 || old - i < 0)) { - refcount_set(r, REFCOUNT_SATURATED); - WARN_ONCE(1, "refcount_t: underflow; use-after-free.\n"); - } + if (unlikely(old < 0 || old - i < 0)) + refcount_warn_saturate(r, REFCOUNT_SUB_UAF); return false; } @@ -291,12 +296,8 @@ static inline __must_check bool refcount_dec_and_test(refcount_t *r) */ static inline void refcount_dec(refcount_t *r) { - int old = atomic_fetch_sub_release(1, &r->refs); - - if (unlikely(old <= 1)) { - refcount_set(r, REFCOUNT_SATURATED); - WARN_ONCE(1, "refcount_t: decrement hit 0; leaking memory.\n"); - } + if (unlikely(atomic_fetch_sub_release(1, &r->refs) <= 1)) + refcount_warn_saturate(r, REFCOUNT_DEC_LEAK); } #else /* CONFIG_REFCOUNT_FULL */ diff --git a/lib/refcount.c b/lib/refcount.c index 3a534fb..8b7e249 100644 --- a/lib/refcount.c +++ b/lib/refcount.c @@ -8,6 +8,34 @@ #include #include +#define REFCOUNT_WARN(str) WARN_ONCE(1, "refcount_t: " str ".\n") + +void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t) +{ + refcount_set(r, REFCOUNT_SATURATED); + + switch (t) { + case REFCOUNT_ADD_NOT_ZERO_OVF: + REFCOUNT_WARN("saturated; leaking memory"); + break; + case REFCOUNT_ADD_OVF: + REFCOUNT_WARN("saturated; leaking memory"); + break; + case REFCOUNT_ADD_UAF: + REFCOUNT_WARN("addition on 0; use-after-free"); + break; + case REFCOUNT_SUB_UAF: + REFCOUNT_WARN("underflow; use-after-free"); + break; + case REFCOUNT_DEC_LEAK: + REFCOUNT_WARN("decrement hit 0; leaking memory"); + break; + default: + REFCOUNT_WARN("unknown saturation event!?"); + } +} +EXPORT_SYMBOL(refcount_warn_saturate); + /** * refcount_dec_if_one - decrement a refcount if it is 1 * @r: the refcount