From patchwork Wed Aug 17 00:20:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9285015 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 7E84160574 for ; Wed, 17 Aug 2016 00:21:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6D6B2287A6 for ; Wed, 17 Aug 2016 00:21:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 619D6288A1; Wed, 17 Aug 2016 00:21:04 +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 0AB22287A6 for ; Wed, 17 Aug 2016 00:21:02 +0000 (UTC) Received: (qmail 31868 invoked by uid 550); 17 Aug 2016 00:20:47 -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 31758 invoked from network); 17 Aug 2016 00:20:44 -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=KqczWFiayefXxVBEZ68WJa9aybyWUvx6cv5VEslIn20ol/mUtUS5v2rc9mDLJtqv7n uEboeri0A2PivfPr6mJ4+cF9xDN1znRi8OaY80ak5oTXocqd9iOXpNg8AsveQwlrwKxx Md0uVChqG1sohMqZ4fnPVWUX5pL8BKA7AbAwg= 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=CzPJJH+/3eBoXMSr6cH/8uwstbT7r8qBU8f3YSG/ngo6XqNfbeDBbvZfRF1d0QMog/ w50UCXR04jeC0ulbJ6jNR/6pYQ3RAsoLlHMaiO5fBf3FJdAb8tfMqua16QG/6pnwS5tj IgOcu0XF0QjOU5SgE/PiZENJ+COFMLjGT8qSBuWEKX9oI9o+3Mhzp73/qpCO1hT+452y PPOyq4HgVa30Hx9/0w8AsEsI80K4c85ZCy1IgvkNkgp7Um8SaoovKzc9E8x7X6T8qPQg u/a5fGBSArMv+ZH8jR4ytODYv19PdcL/YhTiquAHKTieDsHyfTQUCtszFFQUf6qRzEQ5 H37w== X-Gm-Message-State: AEkoousCDTOu1CRQwMiubricpyQyWrmLakMqQyTnSyBncAN5n7gkRr8DxkT072F4OHZw6LSw X-Received: by 10.66.32.131 with SMTP id j3mr70450486pai.58.1471393233202; Tue, 16 Aug 2016 17:20:33 -0700 (PDT) From: Kees Cook To: "Paul E . McKenney" Cc: Kees Cook , Laura Abbott , Steven Rostedt , Stephen Boyd , Daniel Micay , Joe Perches , Arnd Bergmann , Greg Kroah-Hartman , Josh Triplett , Mathieu Desnoyers , Lai Jiangshan , "Aneesh Kumar K.V" , "Kirill A. Shutemov" , Michael Ellerman , Dan Williams , Andrew Morton , Ingo Molnar , Thomas Gleixner , Josef Bacik , Andrey Ryabinin , Tejun Heo , Nikolay Aleksandrov , Dmitry Vyukov , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com Date: Tue, 16 Aug 2016 17:20:27 -0700 Message-Id: <1471393229-27182-4-git-send-email-keescook@chromium.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1471393229-27182-1-git-send-email-keescook@chromium.org> References: <1471393229-27182-1-git-send-email-keescook@chromium.org> Subject: [kernel-hardening] [PATCH v2 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);