Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp423249ybk; Sat, 9 May 2020 07:01:02 -0700 (PDT) X-Google-Smtp-Source: APiQypJkDWomTzOLRaxKPpdQBaPKJQooJbJWCb/Yx2GNEs+D3VEej43PVbJehsNM49tBuaCuFQ09 X-Received: by 2002:a05:6402:1596:: with SMTP id c22mr6610410edv.100.1589032862282; Sat, 09 May 2020 07:01:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589032862; cv=none; d=google.com; s=arc-20160816; b=QUNq8lHNaByH5nJfgqKRXTihRvVAQ4QnkAn5BdeRgiJDD/Q4DOCUCUClf+lqqWtx7k QaD4n6pEixshvXqbBK/2QEK50QT1OBUmdCIGZVVB8COejN/L9hJphOrJsdfp5rNBDDMo rdtA81RLJeeuz/DsQFRMgJSWpaDcS/s9EIjaH/D1HenFVTlOruq1/zuxQQYuC2WrtEOd Kg9C2H9i4hTAfEeL84wefjRrKlaJ3Oq3v5jssq4sYMRPWxCl0o75zKjEIlYa5SsaF9/r dti7z5KmknNtZsbbnbAYJo21FAG6xHk5h2+LPmaUHbyQkWB49njTrtHrOgLa4v9ksYH4 2N/A== 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 :message-id:date:subject:cc:to:from:dkim-signature; bh=nLUA8W5j+MyNDn2SryzaQKTx2p2PalluAUK/eJiFTvA=; b=TkklNg7rl+q79/enZYvn6y++/wz5EzJD/rgFCcuivHQkNevAbyf8zbE90u1H+r7OxB mi9CJuhDt5JCWwAQv8VryzHWAIXfVx+vHFVvMqqCoFn9AdntAv/zjQTIphahTuHuKzFH Cvew+Ro7xK16rYGvjsGZMVwfwctj+Pnaa0s0qchMAjKdfXzPFvX0MTl1a9yCTnUplTOu d515c7IQ4qWFXIL5mkxdmm0TYBLZBD8/HNobuhqJAaRGWErjHudgGVb2GzBZeM0kk/6I 33VnD3+GdrfvzE+wWSzbusd59tari0DTQkxP5h6hKnwSRQCtujBh54T7mhtXQIzQmFyy p8wg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZmZL3ms2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z23si2850539edl.64.2020.05.09.07.00.37; Sat, 09 May 2020 07:01:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZmZL3ms2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727863AbgEIN63 (ORCPT + 99 others); Sat, 9 May 2020 09:58:29 -0400 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:48185 "EHLO us-smtp-1.mimecast.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726782AbgEIN62 (ORCPT ); Sat, 9 May 2020 09:58:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1589032706; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=nLUA8W5j+MyNDn2SryzaQKTx2p2PalluAUK/eJiFTvA=; b=ZmZL3ms2WupMsGIQCqNuDwsWqSqwFLMqS3hzc813xao5/61bkIIHqMuHe4QcjmeakqIZd9 p+E5T4EkeNR+ticYDIt1/BVTd4JAMQfR/8dknBpgnYB5EG4o4mGHYgas8G+MjYn68pmXhJ XblTMgeBk6mu3+PIXb+hFxkbsfvfZIY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-311-CZHajXDuMram0ED9XXXl7g-1; Sat, 09 May 2020 09:58:24 -0400 X-MC-Unique: CZHajXDuMram0ED9XXXl7g-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DE53D39341; Sat, 9 May 2020 13:58:17 +0000 (UTC) Received: from optiplex-lnx.redhat.com (unknown [10.3.128.26]) by smtp.corp.redhat.com (Postfix) with ESMTP id 403855D97B; Sat, 9 May 2020 13:57:40 +0000 (UTC) From: Rafael Aquini To: linux-kernel@vger.kernel.org Cc: linux-doc@vger.kernel.org, kexec@lists.infradead.org, linux-fsdevel@vger.kernel.org, dyoung@redhat.com, bhe@redhat.com, corbet@lwn.net, mcgrof@kernel.org, keescook@chromium.org, akpm@linux-foundation.org, cai@lca.pw, rdunlap@infradead.org, tytso@mit.edu, bunk@kernel.org, torvalds@linux-foundation.org, gregkh@linuxfoundation.org, labbott@redhat.com, jeffm@suse.com, jikos@kernel.org, jeyu@suse.de, tiwai@suse.de, AnDavis@suse.com, rpalethorpe@suse.de Subject: [PATCH v3] kernel: add panic_on_taint Date: Sat, 9 May 2020 09:57:37 -0400 Message-Id: <20200509135737.622299-1-aquini@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Analogously to the introduction of panic_on_warn, this patch introduces a kernel option named panic_on_taint in order to provide a simple and generic way to stop execution and catch a coredump when the kernel gets tainted by any given taint flag. This is useful for debugging sessions as it avoids rebuilding the kernel to explicitly add calls to panic() or BUG() into code sites that introduce the taint flags of interest. Another, perhaps less frequent, use for this option would be as a mean for assuring a security policy (in paranoid mode) case where no single taint is allowed for the running system. Suggested-by: Qian Cai Signed-off-by: Rafael Aquini --- Changelog: * v2: get rid of unnecessary/misguided compiler hints (Luis) * v2: enhance documentation text for the new kernel parameter (Randy) * v3: drop sysctl interface, keep it only as a kernel parameter (Luis) Documentation/admin-guide/kdump/kdump.rst | 10 +++++ .../admin-guide/kernel-parameters.txt | 15 +++++++ include/linux/kernel.h | 2 + kernel/panic.c | 40 +++++++++++++++++++ kernel/sysctl.c | 9 ++++- 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kdump/kdump.rst b/Documentation/admin-guide/kdump/kdump.rst index ac7e131d2935..de3cf6d377cc 100644 --- a/Documentation/admin-guide/kdump/kdump.rst +++ b/Documentation/admin-guide/kdump/kdump.rst @@ -521,6 +521,16 @@ will cause a kdump to occur at the panic() call. In cases where a user wants to specify this during runtime, /proc/sys/kernel/panic_on_warn can be set to 1 to achieve the same behaviour. +Trigger Kdump on add_taint() +============================ + +The kernel parameter, panic_on_taint, calls panic() from within add_taint(), +whenever the value set in this bitmask matches with the bit flag being set +by add_taint(). This will cause a kdump to occur at the panic() call. +In cases where a user wants to specify this during runtime, +/proc/sys/kernel/panic_on_taint can be set to a respective bitmask value +to achieve the same behaviour. + Contact ======= diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 7bc83f3d9bdf..4a69fe49a70d 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3404,6 +3404,21 @@ panic_on_warn panic() instead of WARN(). Useful to cause kdump on a WARN(). + panic_on_taint= [KNL] conditionally panic() in add_taint() + Format: + Specifies, as a string, the TAINT flag set that will + compose a bitmask for calling panic() when the kernel + gets tainted. + See Documentation/admin-guide/tainted-kernels.rst for + details on the taint flags that users can pick to + compose the bitmask to assign to panic_on_taint. + When the string is prefixed with a '-' the bitmask + set in panic_on_taint will be mutually exclusive + with the sysctl knob kernel.tainted, and any attempt + to write to that sysctl will fail with -EINVAL for + any taint value that masks with the flags set for + this option. + crash_kexec_post_notifiers Run kdump after running panic-notifiers and dumping kmsg. This only for the users who doubt kdump always diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 9b7a8d74a9d6..66bc102cb59a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -528,6 +528,8 @@ extern int panic_on_oops; extern int panic_on_unrecovered_nmi; extern int panic_on_io_nmi; extern int panic_on_warn; +extern unsigned long panic_on_taint; +extern bool panic_on_taint_exclusive; extern int sysctl_panic_on_rcu_stall; extern int sysctl_panic_on_stackoverflow; diff --git a/kernel/panic.c b/kernel/panic.c index b69ee9e76cb2..65c62f8a1de8 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,8 @@ static int pause_on_oops_flag; static DEFINE_SPINLOCK(pause_on_oops_lock); bool crash_kexec_post_notifiers; int panic_on_warn __read_mostly; +unsigned long panic_on_taint; +bool panic_on_taint_exclusive = false; int panic_timeout = CONFIG_PANIC_TIMEOUT; EXPORT_SYMBOL_GPL(panic_timeout); @@ -434,6 +437,11 @@ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok) pr_warn("Disabling lock debugging due to kernel taint\n"); set_bit(flag, &tainted_mask); + + if (tainted_mask & panic_on_taint) { + panic_on_taint = 0; + panic("panic_on_taint set ..."); + } } EXPORT_SYMBOL(add_taint); @@ -686,3 +694,35 @@ static int __init oops_setup(char *s) return 0; } early_param("oops", oops_setup); + +static int __init panic_on_taint_setup(char *s) +{ + /* we just ignore panic_on_taint if passed without flags */ + if (!s) + goto out; + + for (; *s; s++) { + int i; + + if (*s == '-') { + panic_on_taint_exclusive = true; + continue; + } + + for (i = 0; i < TAINT_FLAGS_COUNT; i++) { + if (toupper(*s) == taint_flags[i].c_true) { + set_bit(i, &panic_on_taint); + break; + } + } + } + + /* unset exclusive mode if no taint flags were passed on */ + if (panic_on_taint_exclusive && + !(panic_on_taint & ((1UL << TAINT_FLAGS_COUNT) - 1))) + panic_on_taint_exclusive = false; + +out: + return 0; +} +early_param("panic_on_taint", panic_on_taint_setup); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8a176d8727a3..d361ec0420f6 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2623,11 +2623,18 @@ static int proc_taint(struct ctl_table *table, int write, return err; if (write) { + int i; + /* + * If we are relying on panic_on_taint not producing + * false positives due to userland input, bail out + * before setting the requested taint flags. + */ + if (panic_on_taint_exclusive && (tmptaint & panic_on_taint)) + return -EINVAL; /* * Poor man's atomic or. Not worth adding a primitive * to everyone's atomic.h for this */ - int i; for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) { if ((tmptaint >> i) & 1) add_taint(i, LOCKDEP_STILL_OK); -- 2.25.4