Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2546172pxb; Tue, 9 Mar 2021 05:27:08 -0800 (PST) X-Google-Smtp-Source: ABdhPJyxDXsImWcQtKSsUU5cWDr6OdxSzvfAeDpTVJ+m79vxCMHSqPNHeaGkHUSOhvpc32ULanwZ X-Received: by 2002:a17:906:2804:: with SMTP id r4mr20172231ejc.521.1615296427880; Tue, 09 Mar 2021 05:27:07 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615296427; cv=none; d=google.com; s=arc-20160816; b=FXtpZTeyblKKtkiJvha/FhyeJnY/N2mVEiGyDSx49zIUgE1Rmwq/OOKTkCoyVXeU38 a6puvhJwEYbp7iTdfp7rRdyt7d/0c3UcuWQyuD0zBBXcUjDui39NzW3Ao22kfp9NN+l1 Y9lpJ2ZGdKD+6pfzzIRl5GUgVBfHGRRBL+ZVcFyTd5GcfEt6+eSm5vk3fRhL6TdKsU+e Y1XrOT5flSg6lavUAtIrHrkPR7z7uPf2KcmO9oHAJKaMeO0BpBMp+kpMu7w0Ws3yABDq fl+a2QmcIEJYUs7ZwYLqxMqXWrz35oUvD3Elx9RzFgdXyDWg+4xY4nPXuod1FswYTTHL T7DA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:dkim-signature; bh=qJAXU5d3STshdjmo9ZaLGYR5dtJDA06hL5AxGivV8jc=; b=oTNOyI7bsA3DY88iMk0nKs2ucdbt9ovO+XQ/qo+neE4o/Cjr274K0Y5fdQRy8CPKBF orhvhuEmDPtQ5wLJseUDbl52SdtKnsUq5/4FAevIJVyWjRu+d/RZejMBGjziKKweydh+ e2A2fNTgYGw3/uSXUAx52UYmMoBujfpYeXocjxIx9d1Og1nSqMVk60QWaeHqKkzGQjCJ iHm1umUWZqAF5ou8NChNVgg6OHZEzJvXf8aNTYujw/NPrv3OSNV3G2fyLm8Iv20TUt1l mwLAEDuoXsIk+XRsyMrUX74vn3C3TqbaYGj7moAg4g4urqnkNu4TQGIJga7Q7BoUsEU6 SGIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=XsWCn7FE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a3si9144675ejd.310.2021.03.09.05.26.44; Tue, 09 Mar 2021 05:27:07 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=XsWCn7FE; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231571AbhCINZR (ORCPT + 99 others); Tue, 9 Mar 2021 08:25:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44410 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230490AbhCINY5 (ORCPT ); Tue, 9 Mar 2021 08:24:57 -0500 Received: from mail-wr1-x449.google.com (mail-wr1-x449.google.com [IPv6:2a00:1450:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 888ADC06175F for ; Tue, 9 Mar 2021 05:24:56 -0800 (PST) Received: by mail-wr1-x449.google.com with SMTP id s10so6428602wre.0 for ; Tue, 09 Mar 2021 05:24:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=qJAXU5d3STshdjmo9ZaLGYR5dtJDA06hL5AxGivV8jc=; b=XsWCn7FEbcQHbjM9dxNsTqETQgS51uKbFupFpjf3dx8+412Xp2tiES0HRg38MN0yOM Af+KSRIcuY/bnzFr2/3ka4JlYKKpsIm7IEB4h1kuhIX0q6APYlbvIRpuKclHmzANBT3C OwnV+2JXsHQRfASew/ZO71yZ7qafuP+VQM3wQM3VwuINQ8x76HzgG2+h9jXBh7lz1F8F FaEOWI2uV7/4oe5c6Z15ew3vmh6TpVzjRJ8H76njIJPrtUyyLY4jR2OUuxQk0ag3gE2q 9pTM2jk9qhb7pif74pei+YO5Z78Ad9kHJrUgL1aPSd5vfC7hSqkKj/HVSwFPPXGN9sRs /8NA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=qJAXU5d3STshdjmo9ZaLGYR5dtJDA06hL5AxGivV8jc=; b=sl1BfZGowef67e0cZyAt4G0GKqsushWPcZnO/wPRmOOdzORaHhK9drKXaFfuR7x8EE 8Q9doitR3wKs+nXGyQMq2GUYEL79YjVP+s9et/P+/mvPibz8WX1VnzsnRZCQ3qTenBCc OvHIM3IrOiuI+MI1QEoqGmCb6Hq4AlOzvEcIWTv1AO2ILYq5UzVbxL5shRwuJdQkqvBp b5MDwPUQm56Xb+nDyQw6EXlucAULhUz0bWlv6LzVCg/fEU/836w0GCJv68G4UOwkpL8s eJHZsuqMMLppqHIYS4iyb94V2NttChUYOMT9Veiq9VRO+JkXhPK0R9ULjs1JghsSBZVK 7mZA== X-Gm-Message-State: AOAM531k3DR/OJGV3aRAjKR+ICpCgDOdqC0uWLBig8BK2crTuVEjfp+g IxGAOtRb03wZblcK7+A5lG3zR6D2HYHcrk63 X-Received: from andreyknvl3.muc.corp.google.com ([2a00:79e0:15:13:5802:818:ce92:dfef]) (user=andreyknvl job=sendgmr) by 2002:a1c:7715:: with SMTP id t21mr4007265wmi.132.1615296295273; Tue, 09 Mar 2021 05:24:55 -0800 (PST) Date: Tue, 9 Mar 2021 14:24:39 +0100 In-Reply-To: Message-Id: <190fd15c1886654afdec0d19ebebd5ade665b601.1615296150.git.andreyknvl@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.30.1.766.gb4fecdf3b7-goog Subject: [PATCH v3 5/5] kasan, mm: integrate slab init_on_free with HW_TAGS From: Andrey Konovalov To: Andrew Morton , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Vlastimil Babka , Catalin Marinas Cc: Will Deacon , Vincenzo Frascino , Dmitry Vyukov , Andrey Ryabinin , Alexander Potapenko , Marco Elver , Peter Collingbourne , Evgenii Stepanov , Branislav Rankov , Kevin Brodsky , kasan-dev@googlegroups.com, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This change uses the previously added memory initialization feature of HW_TAGS KASAN routines for slab memory when init_on_free is enabled. With this change, memory initialization memset() is no longer called when both HW_TAGS KASAN and init_on_free are enabled. Instead, memory is initialized in KASAN runtime. For SLUB, the memory initialization memset() is moved into slab_free_hook() that currently directly follows the initialization loop. A new argument is added to slab_free_hook() that indicates whether to initialize the memory or not. To avoid discrepancies with which memory gets initialized that can be caused by future changes, both KASAN hook and initialization memset() are put together and a warning comment is added. Combining setting allocation tags with memory initialization improves HW_TAGS KASAN performance when init_on_free is enabled. Reviewed-by: Marco Elver Signed-off-by: Andrey Konovalov --- include/linux/kasan.h | 10 ++++++---- mm/kasan/common.c | 13 +++++++------ mm/slab.c | 15 +++++++++++---- mm/slub.c | 43 ++++++++++++++++++++++++------------------- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 85f2a8786606..ed08c419a687 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -203,11 +203,13 @@ static __always_inline void * __must_check kasan_init_slab_obj( return (void *)object; } -bool __kasan_slab_free(struct kmem_cache *s, void *object, unsigned long ip); -static __always_inline bool kasan_slab_free(struct kmem_cache *s, void *object) +bool __kasan_slab_free(struct kmem_cache *s, void *object, + unsigned long ip, bool init); +static __always_inline bool kasan_slab_free(struct kmem_cache *s, + void *object, bool init) { if (kasan_enabled()) - return __kasan_slab_free(s, object, _RET_IP_); + return __kasan_slab_free(s, object, _RET_IP_, init); return false; } @@ -313,7 +315,7 @@ static inline void *kasan_init_slab_obj(struct kmem_cache *cache, { return (void *)object; } -static inline bool kasan_slab_free(struct kmem_cache *s, void *object) +static inline bool kasan_slab_free(struct kmem_cache *s, void *object, bool init) { return false; } diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 7ea747b18c26..623cf94288a2 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -322,8 +322,8 @@ void * __must_check __kasan_init_slab_obj(struct kmem_cache *cache, return (void *)object; } -static inline bool ____kasan_slab_free(struct kmem_cache *cache, - void *object, unsigned long ip, bool quarantine) +static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *object, + unsigned long ip, bool quarantine, bool init) { u8 tag; void *tagged_object; @@ -351,7 +351,7 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, } kasan_poison(object, round_up(cache->object_size, KASAN_GRANULE_SIZE), - KASAN_KMALLOC_FREE, false); + KASAN_KMALLOC_FREE, init); if ((IS_ENABLED(CONFIG_KASAN_GENERIC) && !quarantine)) return false; @@ -362,9 +362,10 @@ static inline bool ____kasan_slab_free(struct kmem_cache *cache, return kasan_quarantine_put(cache, object); } -bool __kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip) +bool __kasan_slab_free(struct kmem_cache *cache, void *object, + unsigned long ip, bool init) { - return ____kasan_slab_free(cache, object, ip, true); + return ____kasan_slab_free(cache, object, ip, true, init); } static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip) @@ -409,7 +410,7 @@ void __kasan_slab_free_mempool(void *ptr, unsigned long ip) return; kasan_poison(ptr, page_size(page), KASAN_FREE_PAGE, false); } else { - ____kasan_slab_free(page->slab_cache, ptr, ip, false); + ____kasan_slab_free(page->slab_cache, ptr, ip, false, false); } } diff --git a/mm/slab.c b/mm/slab.c index 936dd686dec9..3adfe5bc3e2e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -3425,17 +3425,24 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) static __always_inline void __cache_free(struct kmem_cache *cachep, void *objp, unsigned long caller) { + bool init; + if (is_kfence_address(objp)) { kmemleak_free_recursive(objp, cachep->flags); __kfence_free(objp); return; } - if (unlikely(slab_want_init_on_free(cachep))) + /* + * As memory initialization might be integrated into KASAN, + * kasan_slab_free and initialization memset must be + * kept together to avoid discrepancies in behavior. + */ + init = slab_want_init_on_free(cachep); + if (init && !kasan_has_integrated_init()) memset(objp, 0, cachep->object_size); - - /* Put the object into the quarantine, don't touch it for now. */ - if (kasan_slab_free(cachep, objp)) + /* KASAN might put objp into memory quarantine, delaying its reuse. */ + if (kasan_slab_free(cachep, objp, init)) return; /* Use KCSAN to help debug racy use-after-free. */ diff --git a/mm/slub.c b/mm/slub.c index f53df23760e3..37afe6251bcc 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1532,7 +1532,8 @@ static __always_inline void kfree_hook(void *x) kasan_kfree_large(x); } -static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x) +static __always_inline bool slab_free_hook(struct kmem_cache *s, + void *x, bool init) { kmemleak_free_recursive(x, s->flags); @@ -1558,8 +1559,25 @@ static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x) __kcsan_check_access(x, s->object_size, KCSAN_ACCESS_WRITE | KCSAN_ACCESS_ASSERT); - /* KASAN might put x into memory quarantine, delaying its reuse */ - return kasan_slab_free(s, x); + /* + * As memory initialization might be integrated into KASAN, + * kasan_slab_free and initialization memset's must be + * kept together to avoid discrepancies in behavior. + * + * The initialization memset's clear the object and the metadata, + * but don't touch the SLAB redzone. + */ + if (init) { + int rsize; + + if (!kasan_has_integrated_init()) + memset(kasan_reset_tag(x), 0, s->object_size); + rsize = (s->flags & SLAB_RED_ZONE) ? s->red_left_pad : 0; + memset((char *)kasan_reset_tag(x) + s->inuse, 0, + s->size - s->inuse - rsize); + } + /* KASAN might put x into memory quarantine, delaying its reuse. */ + return kasan_slab_free(s, x, init); } static inline bool slab_free_freelist_hook(struct kmem_cache *s, @@ -1569,10 +1587,9 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s, void *object; void *next = *head; void *old_tail = *tail ? *tail : *head; - int rsize; if (is_kfence_address(next)) { - slab_free_hook(s, next); + slab_free_hook(s, next, false); return true; } @@ -1584,20 +1601,8 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s, object = next; next = get_freepointer(s, object); - if (slab_want_init_on_free(s)) { - /* - * Clear the object and the metadata, but don't touch - * the redzone. - */ - memset(kasan_reset_tag(object), 0, s->object_size); - rsize = (s->flags & SLAB_RED_ZONE) ? s->red_left_pad - : 0; - memset((char *)kasan_reset_tag(object) + s->inuse, 0, - s->size - s->inuse - rsize); - - } /* If object's reuse doesn't have to be delayed */ - if (!slab_free_hook(s, object)) { + if (!slab_free_hook(s, object, slab_want_init_on_free(s))) { /* Move object to the new freelist */ set_freepointer(s, object, *head); *head = object; @@ -3235,7 +3240,7 @@ int build_detached_freelist(struct kmem_cache *s, size_t size, } if (is_kfence_address(object)) { - slab_free_hook(df->s, object); + slab_free_hook(df->s, object, false); __kfence_free(object); p[size] = NULL; /* mark object processed */ return size; -- 2.30.1.766.gb4fecdf3b7-goog