From patchwork Wed Aug 17 21:42:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9286623 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 12CC960839 for ; Wed, 17 Aug 2016 21:42:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 04B372950D for ; Wed, 17 Aug 2016 21:42:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id ED3B429512; Wed, 17 Aug 2016 21:42:50 +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 DCB6D2950D for ; Wed, 17 Aug 2016 21:42:49 +0000 (UTC) Received: (qmail 22242 invoked by uid 550); 17 Aug 2016 21:42:36 -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 22145 invoked from network); 17 Aug 2016 21:42:34 -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=WrGe4UKj/0EE9SfzIon2o14yyxscMNUDI3Lbe8wwaU8=; b=nokZXE4Hr5w9tZzvYznWKFUOu2LSYsoQbII+KpjJdjXOXVLsg4Gese50HF88BKeiuk AAjuwYhyXPw0vrrvEqyMvvCC6M7OMy0x5VxY8AOUO5IkbQifro241RigXFNxY3avkA+l thZTbmelbxPa5CwGZ0QXhnqFOBDIDzVeUMmBU= 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=WrGe4UKj/0EE9SfzIon2o14yyxscMNUDI3Lbe8wwaU8=; b=Xfb5XRPeZRn9wgMlsdH/GJdrTIYyp613uiZiETh05h3uGoiJIM0V31Zr9k0XmgUpNg V+Dg/iV0oYh+uVfv0yb1frTb5nNF32E+MAjimx/tarUjE9HEFL1k3IJxp3AhmbRHtwdm GBnd7tVn+CNJdscY5JISgqX2I7ahzz3XsdCaOC9l++2btEFbgFhdCiyzBztt4adPYFoO Gv9/AY1Dmpww5HuUqcTF+9g3/4At8Q/RBU2FgR6+RfSvbhu/ss9E8oqIeVwUVYo/3Jl3 Atb1s4uJSYZYI4MdIkcfrTDnrPBPJsOQYlAK6IOjPftLShjxCYH01YbQGeVBWMWiTGRu 5bJg== X-Gm-Message-State: AEkoouuHMcCZ99pazgX0LvjdEeOb76LeuWEzlhll9jE1phLNfpBQiKW5609S68bh3mu/c8ya X-Received: by 10.98.87.138 with SMTP id i10mr78619931pfj.16.1471470142500; Wed, 17 Aug 2016 14:42:22 -0700 (PDT) From: Kees Cook To: "Paul E . McKenney" Cc: Kees Cook , Laura Abbott , Steven Rostedt , Daniel Micay , Joe Perches , Stephen Boyd , Syed Rameez Mustafa , Arnd Bergmann , Greg Kroah-Hartman , Josh Triplett , Mathieu Desnoyers , Lai Jiangshan , "Aneesh Kumar K.V" , "Kirill A. Shutemov" , Michael Ellerman , Andrew Morton , Dan Williams , Jan Kara , Thomas Gleixner , Josef Bacik , Ingo Molnar , Tejun Heo , Andrey Ryabinin , Nikolay Aleksandrov , Dmitry Vyukov , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com Date: Wed, 17 Aug 2016 14:42:10 -0700 Message-Id: <1471470132-29499-4-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1471470132-29499-1-git-send-email-keescook@chromium.org> References: <1471470132-29499-1-git-send-email-keescook@chromium.org> Subject: [kernel-hardening] [PATCH v3 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 0ed58591538e..569c1cf80c64 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_valid(struct list_head *new, struct list_head *prev, struct list_head *next); +extern bool __list_del_entry_valid(struct list_head *entry); #else static inline bool __list_add_valid(struct list_head *new, struct list_head *prev, @@ -39,6 +40,10 @@ static inline bool __list_add_valid(struct list_head *new, { return true; } +static inline bool __list_del_entry_valid(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_valid(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 d0b89b9d0736..276565fca2a6 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -39,41 +39,34 @@ bool __list_add_valid(struct list_head *new, struct list_head *prev, } EXPORT_SYMBOL(__list_add_valid); -void __list_del_entry(struct list_head *entry) +bool __list_del_entry_valid(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_valid);