From patchwork Tue Aug 16 21:11:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9284733 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 6DA21607FD for ; Tue, 16 Aug 2016 21:11:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5C1DB28538 for ; Tue, 16 Aug 2016 21:11:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4FE5B28703; Tue, 16 Aug 2016 21:11:52 +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 14AB728538 for ; Tue, 16 Aug 2016 21:11:50 +0000 (UTC) Received: (qmail 8032 invoked by uid 550); 16 Aug 2016 21:11:35 -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: Reply-To: kernel-hardening@lists.openwall.com Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 7767 invoked from network); 16 Aug 2016 21:11:31 -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=KwDMmCcrvsS4DGvpxqQ7xdpPNRGkykikdgkq1H4XVHc=; b=XGGCg1cK7EYnPbr3mFczvgakopNg1jiWMlHUb2acpeZwthMATNWdyVfe/N5PBxppWp YDKGjqvi8r6A0m8M/OBHpX6DZwO19az0zsJMPtk+gr2TUkh0FFtVjhxESoxBNDl4kyzA Fn0sfZ7xEztzh2iSt6Fl6Rgdi8imeoKcanAos= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=KwDMmCcrvsS4DGvpxqQ7xdpPNRGkykikdgkq1H4XVHc=; b=Jwhb3lMTmAZuPPgZcvvDTa9Q6xEfC/dShljq6ZKGYg2Or8m2cR71CFXMJ14D5MCNkj qhmDVUwtBFK8gbenvOoMWE6Kpc53msobZZkhy55ZcE+LqRtYTmF+IlHWnTsYouyvC0iA UINAOXSS6NEfFOP2E+XSYb7MQ4R/LQHNBjV6YfvfPKANPck77EbNjo9FcsAdN0d5q2ea 24zJZDbDHzaYuGpnxPU3XtJrEyFXmIXD22I5lMoaeO6yIk8tWX93s3RGOcKxF83GhS/q VBM397b6xdzIyRGV12vU55wf8dWfFZjOrL6p/4gYHb7Dwg1KH9NpaV47SPEGCy1kGZvJ EuEQ== X-Gm-Message-State: AEkoouvKIQxPxZrG4CpVsFAb7H6ySwnyUwNjiG1DRMkouyrP3ZZ11kCpAl4S+bc0eYPqGTcA X-Received: by 10.66.222.202 with SMTP id qo10mr12071977pac.76.1471381879253; Tue, 16 Aug 2016 14:11:19 -0700 (PDT) From: Kees Cook To: "Paul E . McKenney" Cc: Kees Cook , Stephen Boyd , Daniel Micay , Arnd Bergmann , Greg Kroah-Hartman , Josh Triplett , Steven Rostedt , Mathieu Desnoyers , Lai Jiangshan , Peter Zijlstra , Ingo Molnar , Tejun Heo , Michael Ellerman , "Aneesh Kumar K.V" , "Kirill A. Shutemov" , Andrew Morton , Dan Williams , Jan Kara , Josef Bacik , Thomas Gleixner , Andrey Ryabinin , Nikolay Aleksandrov , Dmitry Vyukov , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com Date: Tue, 16 Aug 2016 14:11:04 -0700 Message-Id: <1471381865-25724-5-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1471381865-25724-1-git-send-email-keescook@chromium.org> References: <1471381865-25724-1-git-send-email-keescook@chromium.org> Subject: [kernel-hardening] [PATCH 4/5] bug: Provide toggle for BUG on data corruption X-Virus-Scanned: ClamAV using ClamSMTP The kernel checks for several cases of data structure corruption under either normal runtime, or under various CONFIG_DEBUG_* settings. When corruption is detected, some systems may want to BUG() immediately instead of letting the corruption continue. Many of these manipulation primitives can be used by security flaws to gain arbitrary memory write control. This provides CONFIG_BUG_ON_CORRUPTION to control newly added BUG() locations. This is inspired by similar hardening in PaX and Grsecurity, and by Stephen Boyd in MSM kernels. Signed-off-by: Kees Cook --- include/linux/bug.h | 7 +++++++ kernel/locking/spinlock_debug.c | 1 + kernel/workqueue.c | 2 ++ lib/Kconfig.debug | 10 ++++++++++ lib/list_debug.c | 7 +++++++ 5 files changed, 27 insertions(+) diff --git a/include/linux/bug.h b/include/linux/bug.h index e51b0709e78d..7e69758dd798 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -118,4 +118,11 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr, } #endif /* CONFIG_GENERIC_BUG */ + +#ifdef CONFIG_BUG_ON_CORRUPTION +# define CORRUPTED_DATA_STRUCTURE true +#else +# define CORRUPTED_DATA_STRUCTURE false +#endif + #endif /* _LINUX_BUG_H */ diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c index 0374a596cffa..d5f833769feb 100644 --- a/kernel/locking/spinlock_debug.c +++ b/kernel/locking/spinlock_debug.c @@ -64,6 +64,7 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) owner ? owner->comm : "", owner ? task_pid_nr(owner) : -1, lock->owner_cpu); + BUG_ON(CORRUPTED_DATA_STRUCTURE); dump_stack(); } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index ef071ca73fc3..ea0132b55eca 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "workqueue_internal.h" @@ -2108,6 +2109,7 @@ __acquires(&pool->lock) current->comm, preempt_count(), task_pid_nr(current), worker->current_func); debug_show_held_locks(current); + BUG_ON(CORRUPTED_DATA_STRUCTURE); dump_stack(); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2307d7c89dac..d64bd6b6fd45 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1987,6 +1987,16 @@ config TEST_STATIC_KEYS If unsure, say N. +config BUG_ON_CORRUPTION + bool "Trigger a BUG when data corruption is detected" + help + Select this option if the kernel should BUG when it encounters + data corruption in various kernel memory structures during checks + added by options like CONFIG_DEBUG_LIST, CONFIG_DEBUG_SPINLOCK, + etc. + + If unsure, say N. + source "samples/Kconfig" source "lib/Kconfig.kgdb" diff --git a/lib/list_debug.c b/lib/list_debug.c index 80e2e40a6a4e..161c7e7d3478 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -26,16 +26,19 @@ bool __list_add_debug(struct list_head *new, if (unlikely(next->prev != prev)) { WARN(1, "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n", prev, next->prev, next); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } if (unlikely(prev->next != next)) { WARN(1, "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n", next, prev->next, prev); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } if (unlikely(new == prev || new == next)) { WARN(1, "list_add double add: new=%p, prev=%p, next=%p.\n", new, prev, next); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } return true; @@ -52,21 +55,25 @@ bool __list_del_entry_debug(struct list_head *entry) if (unlikely(next == LIST_POISON1)) { WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n", entry, LIST_POISON1); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } if (unlikely(prev == LIST_POISON2)) { WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n", entry, LIST_POISON2); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } if (unlikely(prev->next != entry)) { WARN(1, "list_del corruption. prev->next should be %p, but was %p\n", entry, prev->next); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } if (unlikely(next->prev != entry)) { WARN(1, "list_del corruption. next->prev should be %p, but was %p\n", entry, next->prev); + BUG_ON(CORRUPTED_DATA_STRUCTURE); return false; } return true;