From patchwork Tue Aug 16 21:11:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9284725 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 19E77607FD for ; Tue, 16 Aug 2016 21:11:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 08C042860D for ; Tue, 16 Aug 2016 21:11:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F068428703; Tue, 16 Aug 2016 21:11:37 +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 AE35528538 for ; Tue, 16 Aug 2016 21:11:35 +0000 (UTC) Received: (qmail 7804 invoked by uid 550); 16 Aug 2016 21:11:31 -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 7766 invoked from network); 16 Aug 2016 21:11:30 -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=UtWzYattwjOVkOogfJJi8g94RnELwt0eVgExbKtFhOk=; b=i5IjXynoRKIImslebJSxOy6gDR1Pdx5O0ADXOe+zItZj30GRHAlnav74o4yrxWSknQ QHT1sjP7Ql7JGRjGwDHNy3lz6OEmJtxoTmWG8bjy1ydmb9vL5oza2cRr/KwGiTvuuEU1 PVFWsAqudJi24IEFhMIXe0E4DFXXT9A2cAuIg= 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=UtWzYattwjOVkOogfJJi8g94RnELwt0eVgExbKtFhOk=; b=kD6c5bWCMCQKOhyyK0PlkfyeybT2hITr6coEuxLP5ap92IBl5XK1xe7NQ+UTja0hFB P5IVaQNq/kjnkOyhtxdfNXQj/z4yUPyauQIEnGnZzOaAs9LGa1UqsevfYiiVMiZdIXtl ZH5EoIUzyVs6UdlvUsBK5FlOTDQoRQCBWpL7IyznIhJbZ3coU+4iUodJoif2RIpoPV1O KuKnnjbP+tTKDHt2bd9WC/IdBtM0qX6sA9g2DlU4UJwTe63sg0Dxduoie0HvAqef9B+3 lpMaoa7p7/CfGLN/DyCSUqs2ThzxH+aI4Q8NhVKDOnPO/VnBR2+hPZyRTmTvnDBUMv5J YQCA== X-Gm-Message-State: AEkoousyBQ+uG2q8EO9gm0zf6itT7PefxwYyVxAPBS1YKEdjGZdaVbIcGwJDWk25irI4u862 X-Received: by 10.66.142.197 with SMTP id ry5mr16729353pab.143.1471381878792; Tue, 16 Aug 2016 14:11:18 -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:03 -0700 Message-Id: <1471381865-25724-4-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 3/5] list: Split list_del() debug checking into separate function X-Virus-Scanned: ClamAV using ClamSMTP Similar to the list_add() debug consolidation, this consolidates the debug checking performed during CONFIG_DEBUG_LIST, and stops list updates when corruption is found. Refactored from same hardening in PaX and Grsecurity. Signed-off-by: Kees Cook --- include/linux/list.h | 15 +++++++++------ lib/list_debug.c | 53 +++++++++++++++++++++++----------------------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/include/linux/list.h b/include/linux/list.h index c38ff652ab59..09b857a0dda1 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -32,6 +32,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list) extern bool __list_add_debug(struct list_head *new, struct list_head *prev, struct list_head *next); +extern bool __list_del_entry_debug(struct list_head *entry); #else static inline bool __list_add_debug(struct list_head *new, struct list_head *prev, @@ -39,6 +40,10 @@ static inline bool __list_add_debug(struct list_head *new, { return true; } +static inline bool __list_del_entry_debug(struct list_head *entry) +{ + return true; +} #endif /* @@ -106,22 +111,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next) * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ -#ifndef CONFIG_DEBUG_LIST static inline void __list_del_entry(struct list_head *entry) { + if (!__list_del_entry_debug(entry)) + return; + __list_del(entry->prev, entry->next); } static inline void list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); + __list_del_entry(entry); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } -#else -extern void __list_del_entry(struct list_head *entry); -extern void list_del(struct list_head *entry); -#endif /** * list_replace - replace old entry by new one diff --git a/lib/list_debug.c b/lib/list_debug.c index e90a931bd5ab..80e2e40a6a4e 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -42,41 +42,34 @@ bool __list_add_debug(struct list_head *new, } EXPORT_SYMBOL(__list_add_debug); -void __list_del_entry(struct list_head *entry) +bool __list_del_entry_debug(struct list_head *entry) { struct list_head *prev, *next; prev = entry->prev; next = entry->next; - if (WARN(next == LIST_POISON1, - "list_del corruption, %p->next is LIST_POISON1 (%p)\n", - entry, LIST_POISON1) || - WARN(prev == LIST_POISON2, - "list_del corruption, %p->prev is LIST_POISON2 (%p)\n", - entry, LIST_POISON2) || - WARN(prev->next != entry, - "list_del corruption. prev->next should be %p, " - "but was %p\n", entry, prev->next) || - WARN(next->prev != entry, - "list_del corruption. next->prev should be %p, " - "but was %p\n", entry, next->prev)) - return; - - __list_del(prev, next); -} -EXPORT_SYMBOL(__list_del_entry); + if (unlikely(next == LIST_POISON1)) { + WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n", + entry, LIST_POISON1); + return false; + } + if (unlikely(prev == LIST_POISON2)) { + WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n", + entry, LIST_POISON2); + return false; + } + if (unlikely(prev->next != entry)) { + WARN(1, "list_del corruption. prev->next should be %p, but was %p\n", + entry, prev->next); + return false; + } + if (unlikely(next->prev != entry)) { + WARN(1, "list_del corruption. next->prev should be %p, but was %p\n", + entry, next->prev); + return false; + } + return true; -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -void list_del(struct list_head *entry) -{ - __list_del_entry(entry); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; } -EXPORT_SYMBOL(list_del); +EXPORT_SYMBOL(__list_del_entry_debug);