Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp2266432imm; Mon, 28 May 2018 05:05:05 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoEp5Bco5YP3qVjEpXydBYFUYp30/eQFaZDbFYh1RFKvn9o+LF2It5dYvdaet8sdVJNq1pq X-Received: by 2002:a62:3745:: with SMTP id e66-v6mr13169526pfa.43.1527509105902; Mon, 28 May 2018 05:05:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527509105; cv=none; d=google.com; s=arc-20160816; b=jFHrQeKvqyoWdQZfqIgZuJwSiSdxgeL+kdP6wTY0EIDiGvmYyEFO1GMGUATCH+5gF6 woaylffjw3vTKfCUiQV95oRtwoZf6EE6AIzse37IlLjZGt5SjPp62HI7yxQYyUlNaq/x B11ssBB70EFOcVZUjxU+3tEmBZN3/AduYlZDGFfrz13UcxMIf7LMDZxv111ghxxzFT8C kfOaBx+J1AtrANdiCrFbVae9Btna4tU5cWhLmHWBN5izcqR4iEp3UtJNFsYRj1j+1MlT 7/MoxOBZ6PnpUb61YQOPN3cbV0K5KsiqZdVZz1yWjhGv3g9m7ZT5L/5/2sF+zpzlraRY Kwag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=wMoLOQMLysaYNclYh7hKDy64wAuW0Fs1o5XmXw4Am+U=; b=daoCUwt3HbxBSBY0ZXwldTf2DJRleaVfBmyBxiyUy0HlIaFFl0ThCdQUAfD9qzBGvQ vo1nfPRfqV5evmuLL5Qgan4CBGzmFVQpEKkBh1ggviLp4Tn9RDunbQkqGcF3zj0T8Vnh N4bnDXL4iTpWVKc6dA08JgF4ZDeupnY0ni1nZFfVTpOHoQcUh1COZj4DakEvcEgoBtbv 2kUFfMFnTbn5q9z7Np+5gEMQ1AUgIexzJupi5AfALjAU8thSv3nxxCy2cMy93BHWnUI0 6UlEEakvy8nJgyaBu7egkFFiBh4UwFrYy1q01hufmVhefb/VYfnLembh8zfvc/lhk3zi WzyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=wFd2oSmW; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o9-v6si23594550pgp.508.2018.05.28.05.04.51; Mon, 28 May 2018 05:05:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=wFd2oSmW; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1423261AbeE1LG0 (ORCPT + 99 others); Mon, 28 May 2018 07:06:26 -0400 Received: from mail.kernel.org ([198.145.29.99]:53216 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1423219AbeE1LGV (ORCPT ); Mon, 28 May 2018 07:06:21 -0400 Received: from localhost (LFbn-1-12247-202.w90-92.abo.wanadoo.fr [90.92.61.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id AC9FC2089E; Mon, 28 May 2018 11:06:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1527505581; bh=2Jckhjz1CIZ7lWE3qReQRudYWs70XfSlsNoypUQ+oms=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wFd2oSmWb5JlN+11yj/9fpugrWNUikHZPS9bdhkZs2x1Pdg597eGLTArjosJs/dAW 33e47iTiwbx15VtkEXyQ21rYcWFozpFfbA9FcDU80PRCooliUmwYEra98jM3Gt2zcb vArTTY+terGXNdAlIYvHkzYbPUsOsJk+Nvub3508= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andrey Konovalov , Andrey Ryabinin , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Alexander Potapenko , Dmitry Vyukov , Kostya Serebryany , Andrew Morton , Linus Torvalds , Sasha Levin Subject: [PATCH 4.16 056/272] kasan, slub: fix handling of kasan_slab_free hook Date: Mon, 28 May 2018 12:01:29 +0200 Message-Id: <20180528100245.615413705@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180528100240.256525891@linuxfoundation.org> References: <20180528100240.256525891@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Andrey Konovalov [ Upstream commit c3895391df385c6628638f014c87e16f5e2efd45 ] The kasan_slab_free hook's return value denotes whether the reuse of a slab object must be delayed (e.g. when the object is put into memory qurantine). The current way SLUB handles this hook is by ignoring its return value and hardcoding checks similar (but not exactly the same) to the ones performed in kasan_slab_free, which is prone to making mistakes. The main difference between the hardcoded checks and the ones in kasan_slab_free is whether we want to perform a free in case when an invalid-free or a double-free was detected (we don't). This patch changes the way SLUB handles this by: 1. taking into account the return value of kasan_slab_free for each of the objects, that are being freed; 2. reconstructing the freelist of objects to exclude the ones, whose reuse must be delayed. [andreyknvl@google.com: eliminate unnecessary branch in slab_free] Link: http://lkml.kernel.org/r/a62759a2545fddf69b0c034547212ca1eb1b3ce2.1520359686.git.andreyknvl@google.com Link: http://lkml.kernel.org/r/083f58501e54731203801d899632d76175868e97.1519400992.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Acked-by: Andrey Ryabinin Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Kostya Serebryany Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- mm/slub.c | 57 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 23 deletions(-) --- a/mm/slub.c +++ b/mm/slub.c @@ -1362,10 +1362,8 @@ static __always_inline void kfree_hook(v kasan_kfree_large(x, _RET_IP_); } -static __always_inline void *slab_free_hook(struct kmem_cache *s, void *x) +static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x) { - void *freeptr; - kmemleak_free_recursive(x, s->flags); /* @@ -1385,17 +1383,12 @@ static __always_inline void *slab_free_h if (!(s->flags & SLAB_DEBUG_OBJECTS)) debug_check_no_obj_freed(x, s->object_size); - freeptr = get_freepointer(s, x); - /* - * kasan_slab_free() may put x into memory quarantine, delaying its - * reuse. In this case the object's freelist pointer is changed. - */ - kasan_slab_free(s, x, _RET_IP_); - return freeptr; + /* KASAN might put x into memory quarantine, delaying its reuse */ + return kasan_slab_free(s, x, _RET_IP_); } -static inline void slab_free_freelist_hook(struct kmem_cache *s, - void *head, void *tail) +static inline bool slab_free_freelist_hook(struct kmem_cache *s, + void **head, void **tail) { /* * Compiler cannot detect this function can be removed if slab_free_hook() @@ -1406,13 +1399,33 @@ static inline void slab_free_freelist_ho defined(CONFIG_DEBUG_OBJECTS_FREE) || \ defined(CONFIG_KASAN) - void *object = head; - void *tail_obj = tail ? : head; - void *freeptr; + void *object; + void *next = *head; + void *old_tail = *tail ? *tail : *head; + + /* Head and tail of the reconstructed freelist */ + *head = NULL; + *tail = NULL; do { - freeptr = slab_free_hook(s, object); - } while ((object != tail_obj) && (object = freeptr)); + object = next; + next = get_freepointer(s, object); + /* If object's reuse doesn't have to be delayed */ + if (!slab_free_hook(s, object)) { + /* Move object to the new freelist */ + set_freepointer(s, object, *head); + *head = object; + if (!*tail) + *tail = object; + } + } while (object != old_tail); + + if (*head == *tail) + *tail = NULL; + + return *head != NULL; +#else + return true; #endif } @@ -2965,14 +2978,12 @@ static __always_inline void slab_free(st void *head, void *tail, int cnt, unsigned long addr) { - slab_free_freelist_hook(s, head, tail); /* - * slab_free_freelist_hook() could have put the items into quarantine. - * If so, no need to free them. + * With KASAN enabled slab_free_freelist_hook modifies the freelist + * to remove objects, whose reuse must be delayed. */ - if (s->flags & SLAB_KASAN && !(s->flags & SLAB_TYPESAFE_BY_RCU)) - return; - do_slab_free(s, page, head, tail, cnt, addr); + if (slab_free_freelist_hook(s, &head, &tail)) + do_slab_free(s, page, head, tail, cnt, addr); } #ifdef CONFIG_KASAN