From nobody Fri Dec 19 12:28:19 2025 Received: from out-186.mta1.migadu.com (out-186.mta1.migadu.com [95.215.58.186]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6557E3D0AB for ; Tue, 19 Dec 2023 22:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="qtqOsejh" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703024952; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=65Nj55va0LyidH/qJFPAhjUaSN3kZxL0lL8iCsNvyX4=; b=qtqOsejhFRAQXz/SAXNo9IB1G73IEgw3a9jUz4FGb8dWQiMSemlTQ9pIavZ+Zr7zX4kUJ8 0olVIm0l45jMoaa0ZeX7DsQotFdRhNCybCgNQh0s4gGlUfcs17lifVGwAZhMGf9p4P7gCO LcI0++R63ENC8BHKVFsfmjkGqnOvA4Y= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 01/21] kasan: rename kasan_slab_free_mempool to kasan_mempool_poison_object Date: Tue, 19 Dec 2023 23:28:45 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Rename kasan_slab_free_mempool to kasan_mempool_poison_object. kasan_slab_free_mempool is a slightly confusing name: it is unclear whether this function poisons the object when it is freed into mempool or does something when the object is freed from mempool to the underlying allocator. The new name also aligns with other mempool-related KASAN hooks added in the following patches in this series. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 8 ++++---- io_uring/alloc_cache.h | 3 +-- mm/kasan/common.c | 4 ++-- mm/mempool.c | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 72cb693b075b..6310435f528b 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -172,11 +172,11 @@ static __always_inline void kasan_kfree_large(void *p= tr) __kasan_kfree_large(ptr, _RET_IP_); } =20 -void __kasan_slab_free_mempool(void *ptr, unsigned long ip); -static __always_inline void kasan_slab_free_mempool(void *ptr) +void __kasan_mempool_poison_object(void *ptr, unsigned long ip); +static __always_inline void kasan_mempool_poison_object(void *ptr) { if (kasan_enabled()) - __kasan_slab_free_mempool(ptr, _RET_IP_); + __kasan_mempool_poison_object(ptr, _RET_IP_); } =20 void * __must_check __kasan_slab_alloc(struct kmem_cache *s, @@ -256,7 +256,7 @@ static inline bool kasan_slab_free(struct kmem_cache *s= , void *object, bool init return false; } static inline void kasan_kfree_large(void *ptr) {} -static inline void kasan_slab_free_mempool(void *ptr) {} +static inline void kasan_mempool_poison_object(void *ptr) {} static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags, bool init) { diff --git a/io_uring/alloc_cache.h b/io_uring/alloc_cache.h index 241245cb54a6..8de0414e8efe 100644 --- a/io_uring/alloc_cache.h +++ b/io_uring/alloc_cache.h @@ -16,8 +16,7 @@ static inline bool io_alloc_cache_put(struct io_alloc_cac= he *cache, if (cache->nr_cached < cache->max_cached) { cache->nr_cached++; wq_stack_add_head(&entry->node, &cache->list); - /* KASAN poisons object */ - kasan_slab_free_mempool(entry); + kasan_mempool_poison_object(entry); return true; } return false; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index fe6c4b43ad9f..e0394d0ee7f1 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -271,7 +271,7 @@ static inline bool ____kasan_kfree_large(void *ptr, uns= igned long ip) =20 /* * The object will be poisoned by kasan_poison_pages() or - * kasan_slab_free_mempool(). + * kasan_mempool_poison_object(). */ =20 return false; @@ -282,7 +282,7 @@ void __kasan_kfree_large(void *ptr, unsigned long ip) ____kasan_kfree_large(ptr, ip); } =20 -void __kasan_slab_free_mempool(void *ptr, unsigned long ip) +void __kasan_mempool_poison_object(void *ptr, unsigned long ip) { struct folio *folio; =20 diff --git a/mm/mempool.c b/mm/mempool.c index b3d2084fd989..7e1c729f292b 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -107,7 +107,7 @@ static inline void poison_element(mempool_t *pool, void= *element) static __always_inline void kasan_poison_element(mempool_t *pool, void *el= ement) { if (pool->alloc =3D=3D mempool_alloc_slab || pool->alloc =3D=3D mempool_k= malloc) - kasan_slab_free_mempool(element); + kasan_mempool_poison_object(element); else if (pool->alloc =3D=3D mempool_alloc_pages) kasan_poison_pages(element, (unsigned long)pool->pool_data, false); --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-176.mta1.migadu.com (out-176.mta1.migadu.com [95.215.58.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE9E43D0B2 for ; Tue, 19 Dec 2023 22:29:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="UmTZEubK" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703024953; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UD/Zwt/pPZV96U3h6ZFDRBLd7zSWBzdFKqeEs3HVWEE=; b=UmTZEubKzQoH/lyQhsn4scksM491Jqbo0EpqojoHRU0E+cXktICkazzTkFV4YlK3P70GL4 dgY6Fs06IrKmOBcUEU27QhbAyaN4aO/daowtIz1mMORsloednidVgfydYvYT7U3SjZHFk/ +5imE9/lInyqZ2hSS3qnfUmxERlUWdM= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 02/21] kasan: move kasan_mempool_poison_object Date: Tue, 19 Dec 2023 23:28:46 +0100 Message-Id: <23ea215409f43c13cdf9ecc454501a264c107d67.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Move kasan_mempool_poison_object after all slab-related KASAN hooks. This is a preparatory change for the following patches in this series. No functional changes. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 16 +++++++-------- mm/kasan/common.c | 46 +++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 6310435f528b..0d1f925c136d 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -172,13 +172,6 @@ static __always_inline void kasan_kfree_large(void *pt= r) __kasan_kfree_large(ptr, _RET_IP_); } =20 -void __kasan_mempool_poison_object(void *ptr, unsigned long ip); -static __always_inline void kasan_mempool_poison_object(void *ptr) -{ - if (kasan_enabled()) - __kasan_mempool_poison_object(ptr, _RET_IP_); -} - void * __must_check __kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags, bool init); static __always_inline void * __must_check kasan_slab_alloc( @@ -219,6 +212,13 @@ static __always_inline void * __must_check kasan_kreal= loc(const void *object, return (void *)object; } =20 +void __kasan_mempool_poison_object(void *ptr, unsigned long ip); +static __always_inline void kasan_mempool_poison_object(void *ptr) +{ + if (kasan_enabled()) + __kasan_mempool_poison_object(ptr, _RET_IP_); +} + /* * Unlike kasan_check_read/write(), kasan_check_byte() is performed even f= or * the hardware tag-based mode that doesn't rely on compiler instrumentati= on. @@ -256,7 +256,6 @@ static inline bool kasan_slab_free(struct kmem_cache *s= , void *object, bool init return false; } static inline void kasan_kfree_large(void *ptr) {} -static inline void kasan_mempool_poison_object(void *ptr) {} static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags, bool init) { @@ -276,6 +275,7 @@ static inline void *kasan_krealloc(const void *object, = size_t new_size, { return (void *)object; } +static inline void kasan_mempool_poison_object(void *ptr) {} static inline bool kasan_check_byte(const void *address) { return true; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index e0394d0ee7f1..fc7f711607e1 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -282,29 +282,6 @@ void __kasan_kfree_large(void *ptr, unsigned long ip) ____kasan_kfree_large(ptr, ip); } =20 -void __kasan_mempool_poison_object(void *ptr, unsigned long ip) -{ - struct folio *folio; - - folio =3D virt_to_folio(ptr); - - /* - * Even though this function is only called for kmem_cache_alloc and - * kmalloc backed mempool allocations, those allocations can still be - * !PageSlab() when the size provided to kmalloc is larger than - * KMALLOC_MAX_SIZE, and kmalloc falls back onto page_alloc. - */ - if (unlikely(!folio_test_slab(folio))) { - if (____kasan_kfree_large(ptr, ip)) - return; - kasan_poison(ptr, folio_size(folio), KASAN_PAGE_FREE, false); - } else { - struct slab *slab =3D folio_slab(folio); - - ____kasan_slab_free(slab->slab_cache, ptr, ip, false, false); - } -} - void * __must_check __kasan_slab_alloc(struct kmem_cache *cache, void *object, gfp_t flags, bool init) { @@ -452,6 +429,29 @@ void * __must_check __kasan_krealloc(const void *objec= t, size_t size, gfp_t flag return ____kasan_kmalloc(slab->slab_cache, object, size, flags); } =20 +void __kasan_mempool_poison_object(void *ptr, unsigned long ip) +{ + struct folio *folio; + + folio =3D virt_to_folio(ptr); + + /* + * Even though this function is only called for kmem_cache_alloc and + * kmalloc backed mempool allocations, those allocations can still be + * !PageSlab() when the size provided to kmalloc is larger than + * KMALLOC_MAX_SIZE, and kmalloc falls back onto page_alloc. + */ + if (unlikely(!folio_test_slab(folio))) { + if (____kasan_kfree_large(ptr, ip)) + return; + kasan_poison(ptr, folio_size(folio), KASAN_PAGE_FREE, false); + } else { + struct slab *slab =3D folio_slab(folio); + + ____kasan_slab_free(slab->slab_cache, ptr, ip, false, false); + } +} + bool __kasan_check_byte(const void *address, unsigned long ip) { if (!kasan_byte_accessible(address)) { --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-184.mta1.migadu.com (out-184.mta1.migadu.com [95.215.58.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABD083D0B3 for ; Tue, 19 Dec 2023 22:29:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="C4rzmgvl" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703024953; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nDVhwjjwJnVTlqgIL3b0i6xOOMbmQ8bjgeF5HzBvdls=; b=C4rzmgvlL10DUVbNDtuc0Rxs46Curn42ZGKpKom91VOpoIt4fpkrs/ypbw6AsjfsBn5cAV f4+a7vAj+bLJwhOfAkOj0ot52A4kwU/QGW9g6mUQ3jTBsZTJ9qMcuEm6y1mZK7xk4PDRQ1 qJLgEpIfbiitBegq2Oh+ysHOy3abWJw= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 03/21] kasan: document kasan_mempool_poison_object Date: Tue, 19 Dec 2023 23:28:47 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Add documentation comment for kasan_mempool_poison_object. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 0d1f925c136d..bbf6e2fa4ffd 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -213,6 +213,24 @@ static __always_inline void * __must_check kasan_kreal= loc(const void *object, } =20 void __kasan_mempool_poison_object(void *ptr, unsigned long ip); +/** + * kasan_mempool_poison_object - Check and poison a mempool slab allocatio= n. + * @ptr: Pointer to the slab allocation. + * + * This function is intended for kernel subsystems that cache slab allocat= ions + * to reuse them instead of freeing them back to the slab allocator (e.g. + * mempool). + * + * This function poisons a slab allocation without initializing its memory= and + * without putting it into the quarantine (for the Generic mode). + * + * This function also performs checks to detect double-free and invalid-fr= ee + * bugs and reports them. + * + * This function operates on all slab allocations including large kmalloc + * allocations (the ones returned by kmalloc_large() or by kmalloc() with = the + * size > KMALLOC_MAX_SIZE). + */ static __always_inline void kasan_mempool_poison_object(void *ptr) { if (kasan_enabled()) --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-183.mta1.migadu.com (out-183.mta1.migadu.com [95.215.58.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD4873D0B6 for ; Tue, 19 Dec 2023 22:29:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="dzo5xM0U" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703024954; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=W+GO4UdeS5AdNTnDLBObG20S1KoxsxGlKzUPAgkpjho=; b=dzo5xM0U129ISs8wP5QYvHL5occ5Ub/oL2lz1qj/FqHB9brhX1Gfjk4Uw9COo67ZEnW8ww KhbMK460okwgrIt1sc0CA8v8HSc2psAxv4a5/jCjrofVYNGNlcaua/Ot8Y8/UKGJ7gqOyM 9nt9J9X1zm2DTKxesXWV16ZmBqZDjO0= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 04/21] kasan: add return value for kasan_mempool_poison_object Date: Tue, 19 Dec 2023 23:28:48 +0100 Message-Id: <618af65273875fb9f56954285443279b15f1fcd9.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Add a return value for kasan_mempool_poison_object that lets the caller know whether the allocation is affected by a double-free or an invalid-free bug. The caller can use this return value to stop operating on the object. Also introduce a check_page_allocation helper function to improve the code readability. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 17 ++++++++++++----- mm/kasan/common.c | 21 ++++++++++----------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index bbf6e2fa4ffd..33387e254caa 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -212,7 +212,7 @@ static __always_inline void * __must_check kasan_kreall= oc(const void *object, return (void *)object; } =20 -void __kasan_mempool_poison_object(void *ptr, unsigned long ip); +bool __kasan_mempool_poison_object(void *ptr, unsigned long ip); /** * kasan_mempool_poison_object - Check and poison a mempool slab allocatio= n. * @ptr: Pointer to the slab allocation. @@ -225,16 +225,20 @@ void __kasan_mempool_poison_object(void *ptr, unsigne= d long ip); * without putting it into the quarantine (for the Generic mode). * * This function also performs checks to detect double-free and invalid-fr= ee - * bugs and reports them. + * bugs and reports them. The caller can use the return value of this func= tion + * to find out if the allocation is buggy. * * This function operates on all slab allocations including large kmalloc * allocations (the ones returned by kmalloc_large() or by kmalloc() with = the * size > KMALLOC_MAX_SIZE). + * + * Return: true if the allocation can be safely reused; false otherwise. */ -static __always_inline void kasan_mempool_poison_object(void *ptr) +static __always_inline bool kasan_mempool_poison_object(void *ptr) { if (kasan_enabled()) - __kasan_mempool_poison_object(ptr, _RET_IP_); + return __kasan_mempool_poison_object(ptr, _RET_IP_); + return true; } =20 /* @@ -293,7 +297,10 @@ static inline void *kasan_krealloc(const void *object,= size_t new_size, { return (void *)object; } -static inline void kasan_mempool_poison_object(void *ptr) {} +static inline bool kasan_mempool_poison_object(void *ptr) +{ + return true; +} static inline bool kasan_check_byte(const void *address) { return true; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index fc7f711607e1..2b4869de4985 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -254,7 +254,7 @@ bool __kasan_slab_free(struct kmem_cache *cache, void *= object, return ____kasan_slab_free(cache, object, ip, true, init); } =20 -static inline bool ____kasan_kfree_large(void *ptr, unsigned long ip) +static inline bool check_page_allocation(void *ptr, unsigned long ip) { if (!kasan_arch_is_ready()) return false; @@ -269,17 +269,14 @@ static inline bool ____kasan_kfree_large(void *ptr, u= nsigned long ip) return true; } =20 - /* - * The object will be poisoned by kasan_poison_pages() or - * kasan_mempool_poison_object(). - */ - return false; } =20 void __kasan_kfree_large(void *ptr, unsigned long ip) { - ____kasan_kfree_large(ptr, ip); + check_page_allocation(ptr, ip); + + /* The object will be poisoned by kasan_poison_pages(). */ } =20 void * __must_check __kasan_slab_alloc(struct kmem_cache *cache, @@ -429,7 +426,7 @@ void * __must_check __kasan_krealloc(const void *object= , size_t size, gfp_t flag return ____kasan_kmalloc(slab->slab_cache, object, size, flags); } =20 -void __kasan_mempool_poison_object(void *ptr, unsigned long ip) +bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) { struct folio *folio; =20 @@ -442,13 +439,15 @@ void __kasan_mempool_poison_object(void *ptr, unsigne= d long ip) * KMALLOC_MAX_SIZE, and kmalloc falls back onto page_alloc. */ if (unlikely(!folio_test_slab(folio))) { - if (____kasan_kfree_large(ptr, ip)) - return; + if (check_page_allocation(ptr, ip)) + return false; kasan_poison(ptr, folio_size(folio), KASAN_PAGE_FREE, false); + return true; } else { struct slab *slab =3D folio_slab(folio); =20 - ____kasan_slab_free(slab->slab_cache, ptr, ip, false, false); + return !____kasan_slab_free(slab->slab_cache, ptr, ip, + false, false); } } =20 --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-188.mta1.migadu.com (out-188.mta1.migadu.com [95.215.58.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82A073D0C1 for ; Tue, 19 Dec 2023 22:29:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="F86/EPhH" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703024954; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DO8tjmS9YVd+JQvWum2ppGekXJiIG6c57s1H7fN9b9c=; b=F86/EPhH4w6/WbWrDENKsFnnUYgyTxWsWcPGWpBY23pYkD6fHfvr174y/cag/gCnwWPUSr 5v6xLH4KEmbEYh1Enf/9T6dx3MnCR1H0deL92bZhphAwsZ5re8vi40q1doi4AozQsFx4SP 8eXPaY9dqKTzvnqybENGUX0YdLOqPQA= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 05/21] kasan: introduce kasan_mempool_unpoison_object Date: Tue, 19 Dec 2023 23:28:49 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Introduce and document a kasan_mempool_unpoison_object hook. This hook serves as a replacement for the generic kasan_unpoison_range that the mempool code relies on right now. mempool will be updated to use the new hook in one of the following patches. For now, define the new hook to be identical to kasan_unpoison_range. One of the following patches will update it to add stack trace collection. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 31 +++++++++++++++++++++++++++++++ mm/kasan/common.c | 5 +++++ 2 files changed, 36 insertions(+) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 33387e254caa..c5fe303bc1c2 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -228,6 +228,9 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned = long ip); * bugs and reports them. The caller can use the return value of this func= tion * to find out if the allocation is buggy. * + * Before the poisoned allocation can be reused, it must be unpoisoned via + * kasan_mempool_unpoison_object(). + * * This function operates on all slab allocations including large kmalloc * allocations (the ones returned by kmalloc_large() or by kmalloc() with = the * size > KMALLOC_MAX_SIZE). @@ -241,6 +244,32 @@ static __always_inline bool kasan_mempool_poison_objec= t(void *ptr) return true; } =20 +void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long= ip); +/** + * kasan_mempool_unpoison_object - Unpoison a mempool slab allocation. + * @ptr: Pointer to the slab allocation. + * @size: Size to be unpoisoned. + * + * This function is intended for kernel subsystems that cache slab allocat= ions + * to reuse them instead of freeing them back to the slab allocator (e.g. + * mempool). + * + * This function unpoisons a slab allocation that was previously poisoned = via + * kasan_mempool_poison_object() without initializing its memory. For the + * tag-based modes, this function does not assign a new tag to the allocat= ion + * and instead restores the original tags based on the pointer value. + * + * This function operates on all slab allocations including large kmalloc + * allocations (the ones returned by kmalloc_large() or by kmalloc() with = the + * size > KMALLOC_MAX_SIZE). + */ +static __always_inline void kasan_mempool_unpoison_object(void *ptr, + size_t size) +{ + if (kasan_enabled()) + __kasan_mempool_unpoison_object(ptr, size, _RET_IP_); +} + /* * Unlike kasan_check_read/write(), kasan_check_byte() is performed even f= or * the hardware tag-based mode that doesn't rely on compiler instrumentati= on. @@ -301,6 +330,8 @@ static inline bool kasan_mempool_poison_object(void *pt= r) { return true; } +static inline void kasan_mempool_unpoison_object(void *ptr, size_t size) {} + static inline bool kasan_check_byte(const void *address) { return true; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 2b4869de4985..4b85d35bb8ab 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -451,6 +451,11 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned= long ip) } } =20 +void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long= ip) +{ + kasan_unpoison(ptr, size, false); +} + bool __kasan_check_byte(const void *address, unsigned long ip) { if (!kasan_byte_accessible(address)) { --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-176.mta0.migadu.com (out-176.mta0.migadu.com [91.218.175.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBE163D0C1 for ; Tue, 19 Dec 2023 22:30:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="qKyzmQgF" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025017; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uNoAVP0QdjYefiRU2LrZ1wqxo2WmCMSn1BBV5oc4/p4=; b=qKyzmQgFg/Y7DFx/QocHdWjJrVPMWCP48LD0cbTxo/AvGFiyJYN91o7BgFE+N8U+w/yHzN C6OjPdLT2mHcpxPkyqBEu2zYClKYdujcJMMPKEyXb1+/NggG2ze+zsPE+2stPIX/Yx9tta GpLx/JGbzJYPzm4QqujIB6NjsTUMg1k= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 06/21] kasan: introduce kasan_mempool_poison_pages Date: Tue, 19 Dec 2023 23:28:50 +0100 Message-Id: <88dc7340cce28249abf789f6e0c792c317df9ba5.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Introduce and document a kasan_mempool_poison_pages hook to be used by the mempool code instead of kasan_poison_pages. Compated to kasan_poison_pages, the new hook: 1. For the tag-based modes, skips checking and poisoning allocations that were not tagged due to sampling. 2. Checks for double-free and invalid-free bugs. In the future, kasan_poison_pages can also be updated to handle #2, but this is out-of-scope of this series. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 27 +++++++++++++++++++++++++++ mm/kasan/common.c | 23 +++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index c5fe303bc1c2..de2a695ad34d 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -212,6 +212,29 @@ static __always_inline void * __must_check kasan_kreal= loc(const void *object, return (void *)object; } =20 +bool __kasan_mempool_poison_pages(struct page *page, unsigned int order, + unsigned long ip); +/** + * kasan_mempool_poison_pages - Check and poison a mempool page allocation. + * @page: Pointer to the page allocation. + * @order: Order of the allocation. + * + * This function is intended for kernel subsystems that cache page allocat= ions + * to reuse them instead of freeing them back to page_alloc (e.g. mempool). + * + * This function is similar to kasan_mempool_poison_object() but operates = on + * page allocations. + * + * Return: true if the allocation can be safely reused; false otherwise. + */ +static __always_inline bool kasan_mempool_poison_pages(struct page *page, + unsigned int order) +{ + if (kasan_enabled()) + return __kasan_mempool_poison_pages(page, order, _RET_IP_); + return true; +} + bool __kasan_mempool_poison_object(void *ptr, unsigned long ip); /** * kasan_mempool_poison_object - Check and poison a mempool slab allocatio= n. @@ -326,6 +349,10 @@ static inline void *kasan_krealloc(const void *object,= size_t new_size, { return (void *)object; } +static inline bool kasan_mempool_poison_pages(struct page *page, unsigned = int order) +{ + return true; +} static inline bool kasan_mempool_poison_object(void *ptr) { return true; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 4b85d35bb8ab..b416f4c265a4 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -426,6 +426,29 @@ void * __must_check __kasan_krealloc(const void *objec= t, size_t size, gfp_t flag return ____kasan_kmalloc(slab->slab_cache, object, size, flags); } =20 +bool __kasan_mempool_poison_pages(struct page *page, unsigned int order, + unsigned long ip) +{ + unsigned long *ptr; + + if (unlikely(PageHighMem(page))) + return true; + + /* Bail out if allocation was excluded due to sampling. */ + if (!IS_ENABLED(CONFIG_KASAN_GENERIC) && + page_kasan_tag(page) =3D=3D KASAN_TAG_KERNEL) + return true; + + ptr =3D page_address(page); + + if (check_page_allocation(ptr, ip)) + return false; + + kasan_poison(ptr, PAGE_SIZE << order, KASAN_PAGE_FREE, false); + + return true; +} + bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) { struct folio *folio; --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-183.mta0.migadu.com (out-183.mta0.migadu.com [91.218.175.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 796A61DFD7 for ; Tue, 19 Dec 2023 22:30:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="mmCEXgMa" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025018; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WvnDVDl+9gd8JY/2icI2mu85dJxeSXpMDACLsdprvYg=; b=mmCEXgMaxz3LTDhN5Aelii+nb4wwQAwSPgj8RLHqQ7+wmGOwxjtSh8dT+vmH5EYV5C6oSg QM5LoKW2tweYqFLGq6U5930x/xHPsIBo/zhwS0iRxm/r+0RSCb6zBs2bH9dNdRzIbXalym qshEQaM+itGw4MLCZQr6zHqTS6ub/qA= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 07/21] kasan: introduce kasan_mempool_unpoison_pages Date: Tue, 19 Dec 2023 23:28:51 +0100 Message-Id: <239bd9af6176f2cc59f5c25893eb36143184daff.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Introduce and document a new kasan_mempool_unpoison_pages hook to be used by the mempool code instead of kasan_unpoison_pages. This hook is not functionally different from kasan_unpoison_pages, but using it improves the mempool code readability. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 25 +++++++++++++++++++++++++ mm/kasan/common.c | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index de2a695ad34d..f8ebde384bd7 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -225,6 +225,9 @@ bool __kasan_mempool_poison_pages(struct page *page, un= signed int order, * This function is similar to kasan_mempool_poison_object() but operates = on * page allocations. * + * Before the poisoned allocation can be reused, it must be unpoisoned via + * kasan_mempool_unpoison_pages(). + * * Return: true if the allocation can be safely reused; false otherwise. */ static __always_inline bool kasan_mempool_poison_pages(struct page *page, @@ -235,6 +238,27 @@ static __always_inline bool kasan_mempool_poison_pages= (struct page *page, return true; } =20 +void __kasan_mempool_unpoison_pages(struct page *page, unsigned int order, + unsigned long ip); +/** + * kasan_mempool_unpoison_pages - Unpoison a mempool page allocation. + * @page: Pointer to the page allocation. + * @order: Order of the allocation. + * + * This function is intended for kernel subsystems that cache page allocat= ions + * to reuse them instead of freeing them back to page_alloc (e.g. mempool). + * + * This function unpoisons a page allocation that was previously poisoned = by + * kasan_mempool_poison_pages() without zeroing the allocation's memory. F= or + * the tag-based modes, this function assigns a new tag to the allocation. + */ +static __always_inline void kasan_mempool_unpoison_pages(struct page *page, + unsigned int order) +{ + if (kasan_enabled()) + __kasan_mempool_unpoison_pages(page, order, _RET_IP_); +} + bool __kasan_mempool_poison_object(void *ptr, unsigned long ip); /** * kasan_mempool_poison_object - Check and poison a mempool slab allocatio= n. @@ -353,6 +377,7 @@ static inline bool kasan_mempool_poison_pages(struct pa= ge *page, unsigned int or { return true; } +static inline void kasan_mempool_unpoison_pages(struct page *page, unsigne= d int order) {} static inline bool kasan_mempool_poison_object(void *ptr) { return true; diff --git a/mm/kasan/common.c b/mm/kasan/common.c index b416f4c265a4..7ebc001d0fcd 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -449,6 +449,12 @@ bool __kasan_mempool_poison_pages(struct page *page, u= nsigned int order, return true; } =20 +void __kasan_mempool_unpoison_pages(struct page *page, unsigned int order, + unsigned long ip) +{ + __kasan_unpoison_pages(page, order, false); +} + bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) { struct folio *folio; --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9E423C6AC for ; Tue, 19 Dec 2023 22:30:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="aMTrQUR0" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=xReOl/oREsxJLQ8k6aIhVhARLuZMnM3hsCknlxTDelk=; b=aMTrQUR0xLK7BplxYFtE4/Xbs25JDCetJWE5YR0p8XlsH+LA6uU4fkxqdQROa6y+LmxS6E H6/bMd8AJ43AJZtjVMsIrilr90PtruFOb4TzM1ChHIK5W2TnGpASFi8QvV447DisyRfhwH u+nqgpjQtRh+bJSPL6UUsX9RcwPAdbI= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 08/21] kasan: clean up __kasan_mempool_poison_object Date: Tue, 19 Dec 2023 23:28:52 +0100 Message-Id: <4f6fc8840512286c1a96e16e86901082c671677d.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Reorganize the code and reword the comment in __kasan_mempool_poison_object to improve the code readability. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/kasan/common.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 7ebc001d0fcd..3f4a1ed69e03 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -457,27 +457,22 @@ void __kasan_mempool_unpoison_pages(struct page *page= , unsigned int order, =20 bool __kasan_mempool_poison_object(void *ptr, unsigned long ip) { - struct folio *folio; - - folio =3D virt_to_folio(ptr); + struct folio *folio =3D virt_to_folio(ptr); + struct slab *slab; =20 /* - * Even though this function is only called for kmem_cache_alloc and - * kmalloc backed mempool allocations, those allocations can still be - * !PageSlab() when the size provided to kmalloc is larger than - * KMALLOC_MAX_SIZE, and kmalloc falls back onto page_alloc. + * This function can be called for large kmalloc allocation that get + * their memory from page_alloc. Thus, the folio might not be a slab. */ if (unlikely(!folio_test_slab(folio))) { if (check_page_allocation(ptr, ip)) return false; kasan_poison(ptr, folio_size(folio), KASAN_PAGE_FREE, false); return true; - } else { - struct slab *slab =3D folio_slab(folio); - - return !____kasan_slab_free(slab->slab_cache, ptr, ip, - false, false); } + + slab =3D folio_slab(folio); + return !____kasan_slab_free(slab->slab_cache, ptr, ip, false, false); } =20 void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long= ip) --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A6DA3D0D9 for ; Tue, 19 Dec 2023 22:30:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="TbFrSJjR" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hXURpFT5cXmxHd6E+IlRMk2ARDz23DTQrTWld5qdG1E=; b=TbFrSJjRFEHr11m9ihb+YpF44WT4zDOU6SR/gpiWxNk2O2ewimYty9RDE8JeT2bHHQsmaJ 7iHSxvOfzi3HpU9gwdbmyAE7I1nnRqLM1ejSraTyzN977wLeS1qdGvxzBLEl1QotjPd3vl vMCPpPc3Z0zUFBC41bC95eXG8vcuwiQ= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 09/21] kasan: save free stack traces for slab mempools Date: Tue, 19 Dec 2023 23:28:53 +0100 Message-Id: <413a7c7c3344fb56809853339ffaabc9e4905e94.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Make kasan_mempool_poison_object save free stack traces for slab and kmalloc mempools when the object is freed into the mempool. Also simplify and rename ____kasan_slab_free to poison_slab_object and do a few other reability changes. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 5 +++-- mm/kasan/common.c | 20 +++++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index f8ebde384bd7..e636a00e26ba 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -268,8 +268,9 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned = long ip); * to reuse them instead of freeing them back to the slab allocator (e.g. * mempool). * - * This function poisons a slab allocation without initializing its memory= and - * without putting it into the quarantine (for the Generic mode). + * This function poisons a slab allocation and saves a free stack trace fo= r it + * without initializing the allocation's memory and without putting it int= o the + * quarantine (for the Generic mode). * * This function also performs checks to detect double-free and invalid-fr= ee * bugs and reports them. The caller can use the return value of this func= tion diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 3f4a1ed69e03..59146886e57d 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -207,8 +207,8 @@ void * __must_check __kasan_init_slab_obj(struct kmem_c= ache *cache, return (void *)object; } =20 -static inline bool ____kasan_slab_free(struct kmem_cache *cache, void *obj= ect, - unsigned long ip, bool quarantine, bool init) +static inline bool poison_slab_object(struct kmem_cache *cache, void *obje= ct, + unsigned long ip, bool init) { void *tagged_object; =20 @@ -221,13 +221,12 @@ static inline bool ____kasan_slab_free(struct kmem_ca= che *cache, void *object, if (is_kfence_address(object)) return false; =20 - if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=3D - object)) { + if (unlikely(nearest_obj(cache, virt_to_slab(object), object) !=3D object= )) { kasan_report_invalid_free(tagged_object, ip, KASAN_REPORT_INVALID_FREE); return true; } =20 - /* RCU slabs could be legally used after free within the RCU period */ + /* RCU slabs could be legally used after free within the RCU period. */ if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU)) return false; =20 @@ -239,19 +238,18 @@ static inline bool ____kasan_slab_free(struct kmem_ca= che *cache, void *object, kasan_poison(object, round_up(cache->object_size, KASAN_GRANULE_SIZE), KASAN_SLAB_FREE, init); =20 - if ((IS_ENABLED(CONFIG_KASAN_GENERIC) && !quarantine)) - return false; - if (kasan_stack_collection_enabled()) kasan_save_free_info(cache, tagged_object); =20 - return kasan_quarantine_put(cache, object); + return false; } =20 bool __kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip, bool init) { - return ____kasan_slab_free(cache, object, ip, true, init); + bool buggy_object =3D poison_slab_object(cache, object, ip, init); + + return buggy_object ? true : kasan_quarantine_put(cache, object); } =20 static inline bool check_page_allocation(void *ptr, unsigned long ip) @@ -472,7 +470,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned = long ip) } =20 slab =3D folio_slab(folio); - return !____kasan_slab_free(slab->slab_cache, ptr, ip, false, false); + return !poison_slab_object(slab->slab_cache, ptr, ip, false); } =20 void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long= ip) --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-184.mta0.migadu.com (out-184.mta0.migadu.com [91.218.175.184]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C009F3D0DB for ; Tue, 19 Dec 2023 22:30:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Ctrg2ZB1" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025020; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TOZdtH5KljVO+QBwvb475Ri4NSt7i5y2rX8Y2gdn2wY=; b=Ctrg2ZB1vr09mQJDl/g4xpRjwYVqozqH5I/yyeUDJ9kKUUsjofuMXHKU5XEuSmxPXCR5w9 dDaoAQH0Z6U4wMeGi6PrDUTFdO+Rj/pE+kqT96iJ8qj/ZdT+fG6UmURjrqCkw90n3UvUpY cDiRSDo85Tluc4i4aNZ0g57lX0tLRX8= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 10/21] kasan: clean up and rename ____kasan_kmalloc Date: Tue, 19 Dec 2023 23:28:54 +0100 Message-Id: <5881232ad357ec0d59a5b1aefd9e0673a386399a.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Introduce a new poison_kmalloc_redzone helper function that poisons the redzone for kmalloc object. Drop the confusingly named ____kasan_kmalloc function and instead use poison_kmalloc_redzone along with the other required parts of ____kasan_kmalloc in the callers' code. This is a preparatory change for the following patches in this series. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/kasan/common.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 59146886e57d..1217b260abc3 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -312,26 +312,12 @@ void * __must_check __kasan_slab_alloc(struct kmem_ca= che *cache, return tagged_object; } =20 -static inline void *____kasan_kmalloc(struct kmem_cache *cache, +static inline void poison_kmalloc_redzone(struct kmem_cache *cache, const void *object, size_t size, gfp_t flags) { unsigned long redzone_start; unsigned long redzone_end; =20 - if (gfpflags_allow_blocking(flags)) - kasan_quarantine_reduce(); - - if (unlikely(object =3D=3D NULL)) - return NULL; - - if (is_kfence_address(kasan_reset_tag(object))) - return (void *)object; - - /* - * The object has already been unpoisoned by kasan_slab_alloc() for - * kmalloc() or by kasan_krealloc() for krealloc(). - */ - /* * The redzone has byte-level precision for the generic mode. * Partially poison the last object granule to cover the unaligned @@ -355,14 +341,25 @@ static inline void *____kasan_kmalloc(struct kmem_cac= he *cache, if (kasan_stack_collection_enabled() && is_kmalloc_cache(cache)) kasan_save_alloc_info(cache, (void *)object, flags); =20 - /* Keep the tag that was set by kasan_slab_alloc(). */ - return (void *)object; } =20 void * __must_check __kasan_kmalloc(struct kmem_cache *cache, const void *= object, size_t size, gfp_t flags) { - return ____kasan_kmalloc(cache, object, size, flags); + if (gfpflags_allow_blocking(flags)) + kasan_quarantine_reduce(); + + if (unlikely(object =3D=3D NULL)) + return NULL; + + if (is_kfence_address(kasan_reset_tag(object))) + return (void *)object; + + /* The object has already been unpoisoned by kasan_slab_alloc(). */ + poison_kmalloc_redzone(cache, object, size, flags); + + /* Keep the tag that was set by kasan_slab_alloc(). */ + return (void *)object; } EXPORT_SYMBOL(__kasan_kmalloc); =20 @@ -408,6 +405,9 @@ void * __must_check __kasan_krealloc(const void *object= , size_t size, gfp_t flag if (unlikely(object =3D=3D ZERO_SIZE_PTR)) return (void *)object; =20 + if (is_kfence_address(kasan_reset_tag(object))) + return (void *)object; + /* * Unpoison the object's data. * Part of it might already have been unpoisoned, but it's unknown @@ -420,8 +420,10 @@ void * __must_check __kasan_krealloc(const void *objec= t, size_t size, gfp_t flag /* Piggy-back on kmalloc() instrumentation to poison the redzone. */ if (unlikely(!slab)) return __kasan_kmalloc_large(object, size, flags); - else - return ____kasan_kmalloc(slab->slab_cache, object, size, flags); + else { + poison_kmalloc_redzone(slab->slab_cache, object, size, flags); + return (void *)object; + } } =20 bool __kasan_mempool_poison_pages(struct page *page, unsigned int order, --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A54F13D0D5 for ; Tue, 19 Dec 2023 22:30:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="SkAJqCw+" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025021; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+EoZxIVuEAKv7x5FH4zs492QikDHeQQIvGcyYCPoQRk=; b=SkAJqCw+CpgpYcxkKbpNsgiVRs3jZsJLDCK6h/+n2tye0d1nsMHpkQEKaGwzu+Y3ortVD6 2V4tHBKknFNLP7uf44CoMBA1yfnNNq11AYTUObnX7PBrHpXsVtYRLuuPg5ub4gL7k2ldkm fH/a/eow85Q+6vMR0kRodOwNov6scpA= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 11/21] kasan: introduce poison_kmalloc_large_redzone Date: Tue, 19 Dec 2023 23:28:55 +0100 Message-Id: <93317097b668519d76097fb065201b2027436e22.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Split out a poison_kmalloc_large_redzone helper from __kasan_kmalloc_large and use it in the caller's code. This is a preparatory change for the following patches in this series. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/kasan/common.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 1217b260abc3..962805bf5f62 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -363,23 +363,12 @@ void * __must_check __kasan_kmalloc(struct kmem_cache= *cache, const void *object } EXPORT_SYMBOL(__kasan_kmalloc); =20 -void * __must_check __kasan_kmalloc_large(const void *ptr, size_t size, +static inline void poison_kmalloc_large_redzone(const void *ptr, size_t si= ze, gfp_t flags) { unsigned long redzone_start; unsigned long redzone_end; =20 - if (gfpflags_allow_blocking(flags)) - kasan_quarantine_reduce(); - - if (unlikely(ptr =3D=3D NULL)) - return NULL; - - /* - * The object has already been unpoisoned by kasan_unpoison_pages() for - * alloc_pages() or by kasan_krealloc() for krealloc(). - */ - /* * The redzone has byte-level precision for the generic mode. * Partially poison the last object granule to cover the unaligned @@ -389,12 +378,25 @@ void * __must_check __kasan_kmalloc_large(const void = *ptr, size_t size, kasan_poison_last_granule(ptr, size); =20 /* Poison the aligned part of the redzone. */ - redzone_start =3D round_up((unsigned long)(ptr + size), - KASAN_GRANULE_SIZE); + redzone_start =3D round_up((unsigned long)(ptr + size), KASAN_GRANULE_SIZ= E); redzone_end =3D (unsigned long)ptr + page_size(virt_to_page(ptr)); kasan_poison((void *)redzone_start, redzone_end - redzone_start, KASAN_PAGE_REDZONE, false); +} =20 +void * __must_check __kasan_kmalloc_large(const void *ptr, size_t size, + gfp_t flags) +{ + if (gfpflags_allow_blocking(flags)) + kasan_quarantine_reduce(); + + if (unlikely(ptr =3D=3D NULL)) + return NULL; + + /* The object has already been unpoisoned by kasan_unpoison_pages(). */ + poison_kmalloc_large_redzone(ptr, size, flags); + + /* Keep the tag that was set by alloc_pages(). */ return (void *)ptr; } =20 @@ -402,6 +404,9 @@ void * __must_check __kasan_krealloc(const void *object= , size_t size, gfp_t flag { struct slab *slab; =20 + if (gfpflags_allow_blocking(flags)) + kasan_quarantine_reduce(); + if (unlikely(object =3D=3D ZERO_SIZE_PTR)) return (void *)object; =20 @@ -419,11 +424,11 @@ void * __must_check __kasan_krealloc(const void *obje= ct, size_t size, gfp_t flag =20 /* Piggy-back on kmalloc() instrumentation to poison the redzone. */ if (unlikely(!slab)) - return __kasan_kmalloc_large(object, size, flags); - else { + poison_kmalloc_large_redzone(object, size, flags); + else poison_kmalloc_redzone(slab->slab_cache, object, size, flags); - return (void *)object; - } + + return (void *)object; } =20 bool __kasan_mempool_poison_pages(struct page *page, unsigned int order, --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55A553D0D0 for ; Tue, 19 Dec 2023 22:31:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="r2ZaOIS6" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025083; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=g+O4MJvijsH/fxNfhEtO0ZT1bhv1NQvjMHnoD8zQplM=; b=r2ZaOIS6ZMwbcRwAxJW59qk9nmH2ETUbfqjNUSa+35AQ7mxBRhFueCynEMDfgvcNnxrrtH sElLzMZVBT/HNZgRFD9eQQjvBsU+nFyNWnkw46nJ6bBbaBE5Zd1NMueq/it/uzQfhtXh75 B0otrG1zpXfsZNehE7M3FBuN9mYYkzY= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 12/21] kasan: save alloc stack traces for mempool Date: Tue, 19 Dec 2023 23:28:56 +0100 Message-Id: <05ad235da8347cfe14d496d01b2aaf074b4f607c.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Update kasan_mempool_unpoison_object to properly poison the redzone and save alloc strack traces for kmalloc and slab pools. As a part of this change, split out and use a unpoison_slab_object helper function from __kasan_slab_alloc. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 7 +++--- mm/kasan/common.c | 50 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index e636a00e26ba..7392c5d89b92 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -303,9 +303,10 @@ void __kasan_mempool_unpoison_object(void *ptr, size_t= size, unsigned long ip); * mempool). * * This function unpoisons a slab allocation that was previously poisoned = via - * kasan_mempool_poison_object() without initializing its memory. For the - * tag-based modes, this function does not assign a new tag to the allocat= ion - * and instead restores the original tags based on the pointer value. + * kasan_mempool_poison_object() and saves an alloc stack trace for it wit= hout + * initializing the allocation's memory. For the tag-based modes, this fun= ction + * does not assign a new tag to the allocation and instead restores the + * original tags based on the pointer value. * * This function operates on all slab allocations including large kmalloc * allocations (the ones returned by kmalloc_large() or by kmalloc() with = the diff --git a/mm/kasan/common.c b/mm/kasan/common.c index 962805bf5f62..b8e7416f83af 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -277,6 +277,20 @@ void __kasan_kfree_large(void *ptr, unsigned long ip) /* The object will be poisoned by kasan_poison_pages(). */ } =20 +void unpoison_slab_object(struct kmem_cache *cache, void *object, gfp_t fl= ags, + bool init) +{ + /* + * Unpoison the whole object. For kmalloc() allocations, + * poison_kmalloc_redzone() will do precise poisoning. + */ + kasan_unpoison(object, cache->object_size, init); + + /* Save alloc info (if possible) for non-kmalloc() allocations. */ + if (kasan_stack_collection_enabled() && !is_kmalloc_cache(cache)) + kasan_save_alloc_info(cache, object, flags); +} + void * __must_check __kasan_slab_alloc(struct kmem_cache *cache, void *object, gfp_t flags, bool init) { @@ -299,15 +313,8 @@ void * __must_check __kasan_slab_alloc(struct kmem_cac= he *cache, tag =3D assign_tag(cache, object, false); tagged_object =3D set_tag(object, tag); =20 - /* - * Unpoison the whole object. - * For kmalloc() allocations, kasan_kmalloc() will do precise poisoning. - */ - kasan_unpoison(tagged_object, cache->object_size, init); - - /* Save alloc info (if possible) for non-kmalloc() allocations. */ - if (kasan_stack_collection_enabled() && !is_kmalloc_cache(cache)) - kasan_save_alloc_info(cache, tagged_object, flags); + /* Unpoison the object and save alloc info for non-kmalloc() allocations.= */ + unpoison_slab_object(cache, tagged_object, flags, init); =20 return tagged_object; } @@ -482,7 +489,30 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned= long ip) =20 void __kasan_mempool_unpoison_object(void *ptr, size_t size, unsigned long= ip) { - kasan_unpoison(ptr, size, false); + struct slab *slab; + gfp_t flags =3D 0; /* Might be executing under a lock. */ + + if (is_kfence_address(kasan_reset_tag(ptr))) + return; + + slab =3D virt_to_slab(ptr); + + /* + * This function can be called for large kmalloc allocation that get + * their memory from page_alloc. + */ + if (unlikely(!slab)) { + kasan_unpoison(ptr, size, false); + poison_kmalloc_large_redzone(ptr, size, flags); + return; + } + + /* Unpoison the object and save alloc info for non-kmalloc() allocations.= */ + unpoison_slab_object(slab->slab_cache, ptr, size, flags); + + /* Poison the redzone and save alloc info for kmalloc() allocations. */ + if (is_kmalloc_cache(slab->slab_cache)) + poison_kmalloc_redzone(slab->slab_cache, ptr, size, flags); } =20 bool __kasan_check_byte(const void *address, unsigned long ip) --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC21F3D0AB for ; Tue, 19 Dec 2023 22:31:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Kt1rNfuv" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025084; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KVsX1wYh/u3bsgXc0v6541Y+g0kgoewEBIuD2sVrVOE=; b=Kt1rNfuvx7+wT5H8UNOgwHCeTbOEvaDygKRpZZi3u1FYmus+bD/11ubTVW79B+oIdiaNwz JlwOYJnlQA+xJy+dqmZh3LmC25rgn5CNTohHAkyMco9Blc+/P3IIuddLLDTvM6CJy8A9+O KeuWbai25yfJ/zAiqqyvZxcC5VTNrDs= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 13/21] mempool: skip slub_debug poisoning when KASAN is enabled Date: Tue, 19 Dec 2023 23:28:57 +0100 Message-Id: <98a4b1617e8ceeb266ef9a46f5e8c7f67a563ad2.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov With the changes in the following patch, KASAN starts saving its metadata within freed mempool elements. Thus, skip slub_debug poisoning and checking of mempool elements when KASAN is enabled. Corruptions of freed mempool elements will be detected by KASAN anyway. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- Changes RFC->v1: - This is a new patch. --- mm/mempool.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/mempool.c b/mm/mempool.c index 7e1c729f292b..1fd39478c85e 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -56,6 +56,10 @@ static void __check_element(mempool_t *pool, void *eleme= nt, size_t size) =20 static void check_element(mempool_t *pool, void *element) { + /* Skip checking: KASAN might save its metadata in the element. */ + if (kasan_enabled()) + return; + /* Mempools backed by slab allocator */ if (pool->free =3D=3D mempool_kfree) { __check_element(pool, element, (size_t)pool->pool_data); @@ -81,6 +85,10 @@ static void __poison_element(void *element, size_t size) =20 static void poison_element(mempool_t *pool, void *element) { + /* Skip poisoning: KASAN might save its metadata in the element. */ + if (kasan_enabled()) + return; + /* Mempools backed by slab allocator */ if (pool->alloc =3D=3D mempool_kmalloc) { __poison_element(element, (size_t)pool->pool_data); --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-189.mta0.migadu.com (out-189.mta0.migadu.com [91.218.175.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7BE023D0BC for ; Tue, 19 Dec 2023 22:31:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="fbafFq1j" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025084; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZKMuCi1Fs+yi8i1iMj8jEYKxpwLo+oL8GkzWTmOTGSI=; b=fbafFq1jlKC1cw8l0es+kRgSLJMag+jZz1zaVwws6qJ/XwEE/QAU3b2QRQ4d4gY3ik5ERb tj3mXVFI3saO1VRCl/G6F+6cQtebPvlWXWmXRbKaD42JplnE469NR+x6bSXKkfuSwR+j0Y wmoNA/R34bjTYOY+bjg9F2pqKV9n4xU= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 14/21] mempool: use new mempool KASAN hooks Date: Tue, 19 Dec 2023 23:28:58 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Update the mempool code to use the new mempool KASAN hooks. Rely on the return value of kasan_mempool_poison_object and kasan_mempool_poison_pages to prevent double-free and invalid-free bugs. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/mempool.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/mm/mempool.c b/mm/mempool.c index 1fd39478c85e..103dc4770cfb 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -112,32 +112,34 @@ static inline void poison_element(mempool_t *pool, vo= id *element) } #endif /* CONFIG_DEBUG_SLAB || CONFIG_SLUB_DEBUG_ON */ =20 -static __always_inline void kasan_poison_element(mempool_t *pool, void *el= ement) +static __always_inline bool kasan_poison_element(mempool_t *pool, void *el= ement) { if (pool->alloc =3D=3D mempool_alloc_slab || pool->alloc =3D=3D mempool_k= malloc) - kasan_mempool_poison_object(element); + return kasan_mempool_poison_object(element); else if (pool->alloc =3D=3D mempool_alloc_pages) - kasan_poison_pages(element, (unsigned long)pool->pool_data, - false); + return kasan_mempool_poison_pages(element, + (unsigned long)pool->pool_data); + return true; } =20 static void kasan_unpoison_element(mempool_t *pool, void *element) { if (pool->alloc =3D=3D mempool_kmalloc) - kasan_unpoison_range(element, (size_t)pool->pool_data); + kasan_mempool_unpoison_object(element, (size_t)pool->pool_data); else if (pool->alloc =3D=3D mempool_alloc_slab) - kasan_unpoison_range(element, kmem_cache_size(pool->pool_data)); + kasan_mempool_unpoison_object(element, + kmem_cache_size(pool->pool_data)); else if (pool->alloc =3D=3D mempool_alloc_pages) - kasan_unpoison_pages(element, (unsigned long)pool->pool_data, - false); + kasan_mempool_unpoison_pages(element, + (unsigned long)pool->pool_data); } =20 static __always_inline void add_element(mempool_t *pool, void *element) { BUG_ON(pool->curr_nr >=3D pool->min_nr); poison_element(pool, element); - kasan_poison_element(pool, element); - pool->elements[pool->curr_nr++] =3D element; + if (kasan_poison_element(pool, element)) + pool->elements[pool->curr_nr++] =3D element; } =20 static void *remove_element(mempool_t *pool) --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-177.mta0.migadu.com (out-177.mta0.migadu.com [91.218.175.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D64AE3D0C4 for ; Tue, 19 Dec 2023 22:31:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="CZpopGBZ" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025085; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Vw9Ju+XsuH7jTh0rV53QjnTfccLPGDaCnQHzua8vht8=; b=CZpopGBZsYX+uocBYMIAfDP7PDv7NGAgHL88CMPaHeNmC1Jd3UkHAbZqq1SXvnp8qR3PRk ko3vkaTQDOJV582w6cY6Jpq7gGMvDm6ekS2hgFsxwAQMhisoeEHQlLiOfoxsL6ydfk5Smi uW9JPOVYPoMNbIRTQbjw3x7wa9H6dN4= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 15/21] mempool: introduce mempool_use_prealloc_only Date: Tue, 19 Dec 2023 23:28:59 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Introduce a new mempool_alloc_preallocated API that asks the mempool to only use the elements preallocated during the mempool's creation when allocating and to not attempt allocating new ones from the underlying allocator. This API is required to test the KASAN poisoning/unpoisoning functionality in KASAN tests, but it might be also useful on its own. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- Changes RFC->v1: - Introduce a new mempool_alloc_preallocated API instead of adding a flag into mempool_t. --- include/linux/mempool.h | 1 + mm/mempool.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/linux/mempool.h b/include/linux/mempool.h index 4aae6c06c5f2..7be1e32e6d42 100644 --- a/include/linux/mempool.h +++ b/include/linux/mempool.h @@ -51,6 +51,7 @@ extern mempool_t *mempool_create_node(int min_nr, mempool= _alloc_t *alloc_fn, extern int mempool_resize(mempool_t *pool, int new_min_nr); extern void mempool_destroy(mempool_t *pool); extern void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask) __malloc; +extern void *mempool_alloc_preallocated(mempool_t *pool) __malloc; extern void mempool_free(void *element, mempool_t *pool); =20 /* diff --git a/mm/mempool.c b/mm/mempool.c index 103dc4770cfb..cb7b4b56cec1 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -456,6 +456,43 @@ void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask) } EXPORT_SYMBOL(mempool_alloc); =20 +/** + * mempool_alloc_preallocated - allocate an element from preallocated elem= ents + * belonging to a specific memory pool + * @pool: pointer to the memory pool which was allocated via + * mempool_create(). + * + * This function is similar to mempool_alloc, but it only attempts allocat= ing + * an element from the preallocated elements. It does not sleep and immedi= ately + * returns if no preallocated elements are available. + * + * Return: pointer to the allocated element or %NULL if no elements are + * available. + */ +void *mempool_alloc_preallocated(mempool_t *pool) +{ + void *element; + unsigned long flags; + + spin_lock_irqsave(&pool->lock, flags); + if (likely(pool->curr_nr)) { + element =3D remove_element(pool); + spin_unlock_irqrestore(&pool->lock, flags); + /* paired with rmb in mempool_free(), read comment there */ + smp_wmb(); + /* + * Update the allocation stack trace as this is more useful + * for debugging. + */ + kmemleak_update_trace(element); + return element; + } + spin_unlock_irqrestore(&pool->lock, flags); + + return NULL; +} +EXPORT_SYMBOL(mempool_alloc_preallocated); + /** * mempool_free - return an element to the pool. * @element: pool element pointer. --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-173.mta0.migadu.com (out-173.mta0.migadu.com [91.218.175.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99CAD3D0CB for ; Tue, 19 Dec 2023 22:31:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="YqrnJgAl" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025085; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gqTGbtVMui+CmtAk7WElvDUhOKijpogQXuGURBykLZ0=; b=YqrnJgAlquajDIl5bS/SUbEt3hHi1yePvIngCNhvy5NPjLJtH9NzR2DNcrEbXuO3mTgAfc WnRYQEnVKDzcn1NHeUUzpzPRb5b+Jnvi9IT8lvOHAJ8lZl5px1Dta7PJmc5FDtpmw3a9kE xUWaYEaCnbJDSFV/GGHi3rjbRbq5pM0= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 16/21] kasan: add mempool tests Date: Tue, 19 Dec 2023 23:29:00 +0100 Message-Id: <5fd64732266be8287711b6408d86ffc78784be06.1703024586.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Add KASAN tests for mempool. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- Changes RFC->v1: - Use read instead of write in oob_right tests to avoid triggering slub_debug-detected corruptions. - Adapt tests for the mempool API change. --- mm/kasan/kasan_test.c | 319 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c index 8281eb42464b..0ae4e93e9311 100644 --- a/mm/kasan/kasan_test.c +++ b/mm/kasan/kasan_test.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -798,6 +799,312 @@ static void kmem_cache_bulk(struct kunit *test) kmem_cache_destroy(cache); } =20 +static void *mempool_prepare_kmalloc(struct kunit *test, mempool_t *pool, = size_t size) +{ + int pool_size =3D 4; + int ret; + void *elem; + + memset(pool, 0, sizeof(*pool)); + ret =3D mempool_init_kmalloc_pool(pool, pool_size, size); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* + * Allocate one element to prevent mempool from freeing elements to the + * underlying allocator and instead make it add them to the element + * list when the tests trigger double-free and invalid-free bugs. + * This allows testing KASAN annotations in add_element(). + */ + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + return elem; +} + +static struct kmem_cache *mempool_prepare_slab(struct kunit *test, mempool= _t *pool, size_t size) +{ + struct kmem_cache *cache; + int pool_size =3D 4; + int ret; + + cache =3D kmem_cache_create("test_cache", size, 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); + + memset(pool, 0, sizeof(*pool)); + ret =3D mempool_init_slab_pool(pool, pool_size, cache); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* + * Do not allocate one preallocated element, as we skip the double-free + * and invalid-free tests for slab mempool for simplicity. + */ + + return cache; +} + +static void *mempool_prepare_page(struct kunit *test, mempool_t *pool, int= order) +{ + int pool_size =3D 4; + int ret; + void *elem; + + memset(pool, 0, sizeof(*pool)); + ret =3D mempool_init_page_pool(pool, pool_size, order); + KUNIT_ASSERT_EQ(test, ret, 0); + + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + return elem; +} + +static void mempool_oob_right_helper(struct kunit *test, mempool_t *pool, = size_t size) +{ + char *elem; + + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + OPTIMIZER_HIDE_VAR(elem); + + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) + KUNIT_EXPECT_KASAN_FAIL(test, + ((volatile char *)&elem[size])[0]); + else + KUNIT_EXPECT_KASAN_FAIL(test, + ((volatile char *)&elem[round_up(size, KASAN_GRANULE_SIZE)])[0]); + + mempool_free(elem, pool); +} + +static void mempool_kmalloc_oob_right(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 128 - KASAN_GRANULE_SIZE - 5; + void *extra_elem; + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_oob_right_helper(test, &pool, size); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_kmalloc_large_oob_right(struct kunit *test) +{ + mempool_t pool; + size_t size =3D KMALLOC_MAX_CACHE_SIZE + 1; + void *extra_elem; + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_oob_right_helper(test, &pool, size); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_slab_oob_right(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 123; + struct kmem_cache *cache; + + cache =3D mempool_prepare_slab(test, &pool, size); + + mempool_oob_right_helper(test, &pool, size); + + mempool_exit(&pool); + kmem_cache_destroy(cache); +} + +/* + * Skip the out-of-bounds test for page mempool. With Generic KASAN, page + * allocations have no redzones, and thus the out-of-bounds detection is n= ot + * guaranteed; see https://bugzilla.kernel.org/show_bug.cgi?id=3D210503. W= ith + * the tag-based KASAN modes, the neighboring allocation might have the sa= me + * tag; see https://bugzilla.kernel.org/show_bug.cgi?id=3D203505. + */ + +static void mempool_uaf_helper(struct kunit *test, mempool_t *pool, bool p= age) +{ + char *elem, *ptr; + + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + mempool_free(elem, pool); + + ptr =3D page ? page_address((struct page *)elem) : elem; + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); +} + +static void mempool_kmalloc_uaf(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 128; + void *extra_elem; + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_uaf_helper(test, &pool, false); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_kmalloc_large_uaf(struct kunit *test) +{ + mempool_t pool; + size_t size =3D KMALLOC_MAX_CACHE_SIZE + 1; + void *extra_elem; + + /* page_alloc fallback is only implemented for SLUB. */ + KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_uaf_helper(test, &pool, false); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_slab_uaf(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 123; + struct kmem_cache *cache; + + cache =3D mempool_prepare_slab(test, &pool, size); + + mempool_uaf_helper(test, &pool, false); + + mempool_exit(&pool); + kmem_cache_destroy(cache); +} + +static void mempool_page_alloc_uaf(struct kunit *test) +{ + mempool_t pool; + int order =3D 2; + void *extra_elem; + + extra_elem =3D mempool_prepare_page(test, &pool, order); + + mempool_uaf_helper(test, &pool, true); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_double_free_helper(struct kunit *test, mempool_t *pool) +{ + char *elem; + + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + mempool_free(elem, pool); + + KUNIT_EXPECT_KASAN_FAIL(test, mempool_free(elem, pool)); +} + +static void mempool_kmalloc_double_free(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 128; + char *extra_elem; + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_double_free_helper(test, &pool); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_kmalloc_large_double_free(struct kunit *test) +{ + mempool_t pool; + size_t size =3D KMALLOC_MAX_CACHE_SIZE + 1; + char *extra_elem; + + /* page_alloc fallback is only implemented for SLUB. */ + KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_double_free_helper(test, &pool); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_page_alloc_double_free(struct kunit *test) +{ + mempool_t pool; + int order =3D 2; + char *extra_elem; + + extra_elem =3D mempool_prepare_page(test, &pool, order); + + mempool_double_free_helper(test, &pool); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_kmalloc_invalid_free_helper(struct kunit *test, mempoo= l_t *pool) +{ + char *elem; + + elem =3D mempool_alloc_preallocated(pool); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elem); + + KUNIT_EXPECT_KASAN_FAIL(test, mempool_free(elem + 1, pool)); + + mempool_free(elem, pool); +} + +static void mempool_kmalloc_invalid_free(struct kunit *test) +{ + mempool_t pool; + size_t size =3D 128; + char *extra_elem; + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_kmalloc_invalid_free_helper(test, &pool); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +static void mempool_kmalloc_large_invalid_free(struct kunit *test) +{ + mempool_t pool; + size_t size =3D KMALLOC_MAX_CACHE_SIZE + 1; + char *extra_elem; + + /* page_alloc fallback is only implemented for SLUB. */ + KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); + + extra_elem =3D mempool_prepare_kmalloc(test, &pool, size); + + mempool_kmalloc_invalid_free_helper(test, &pool); + + mempool_free(extra_elem, &pool); + mempool_exit(&pool); +} + +/* + * Skip the invalid-free test for page mempool. The invalid-free detection= only + * works for compound pages and mempool preallocates all page elements wit= hout + * the __GFP_COMP flag. + */ + static char global_array[10]; =20 static void kasan_global_oob_right(struct kunit *test) @@ -1538,6 +1845,18 @@ static struct kunit_case kasan_kunit_test_cases[] = =3D { KUNIT_CASE(kmem_cache_oob), KUNIT_CASE(kmem_cache_accounted), KUNIT_CASE(kmem_cache_bulk), + KUNIT_CASE(mempool_kmalloc_oob_right), + KUNIT_CASE(mempool_kmalloc_large_oob_right), + KUNIT_CASE(mempool_slab_oob_right), + KUNIT_CASE(mempool_kmalloc_uaf), + KUNIT_CASE(mempool_kmalloc_large_uaf), + KUNIT_CASE(mempool_slab_uaf), + KUNIT_CASE(mempool_page_alloc_uaf), + KUNIT_CASE(mempool_kmalloc_double_free), + KUNIT_CASE(mempool_kmalloc_large_double_free), + KUNIT_CASE(mempool_page_alloc_double_free), + KUNIT_CASE(mempool_kmalloc_invalid_free), + KUNIT_CASE(mempool_kmalloc_large_invalid_free), KUNIT_CASE(kasan_global_oob_right), KUNIT_CASE(kasan_global_oob_left), KUNIT_CASE(kasan_stack_oob), --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-176.mta0.migadu.com (out-176.mta0.migadu.com [91.218.175.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34A363D0CE for ; Tue, 19 Dec 2023 22:31:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Iwn4kg+j" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025086; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vtcYZCAnAciS7NEDq4A0NBDaIMQC+9FU2xLXkQaUBC0=; b=Iwn4kg+js3TZqTZyBEzr5jlkex5ITD9Q+U+eV8TWaTbadaxxhhpExvz32AObLkyzYsWKVo MEGpKSGLfb3aHTx+3wLZBhFQ6hI849in9n+2J9o44vahne4V4yCGCqK7fWLB18LfLjC7TQ S1SacVIxMXkVgZHMVh+q2zV1q3hj0X0= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 17/21] kasan: rename pagealloc tests Date: Tue, 19 Dec 2023 23:29:01 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Rename "pagealloc" KASAN tests: 1. Use "kmalloc_large" for tests that use large kmalloc allocations. 2. Use "page_alloc" for tests that use page_alloc. Also clean up the comments. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/kasan/kasan_test.c | 51 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c index 0ae4e93e9311..230958de7604 100644 --- a/mm/kasan/kasan_test.c +++ b/mm/kasan/kasan_test.c @@ -214,12 +214,13 @@ static void kmalloc_node_oob_right(struct kunit *test) } =20 /* - * These kmalloc_pagealloc_* tests try allocating a memory chunk that does= n't - * fit into a slab cache and therefore is allocated via the page allocator - * fallback. Since this kind of fallback is only implemented for SLUB, the= se - * tests are limited to that allocator. + * The kmalloc_large_* tests below use kmalloc() to allocate a memory chunk + * that does not fit into the largest slab cache and therefore is allocate= d via + * the page_alloc fallback for SLUB. SLAB has no such fallback, and thus t= hese + * tests are not supported for it. */ -static void kmalloc_pagealloc_oob_right(struct kunit *test) + +static void kmalloc_large_oob_right(struct kunit *test) { char *ptr; size_t size =3D KMALLOC_MAX_CACHE_SIZE + 10; @@ -235,7 +236,7 @@ static void kmalloc_pagealloc_oob_right(struct kunit *t= est) kfree(ptr); } =20 -static void kmalloc_pagealloc_uaf(struct kunit *test) +static void kmalloc_large_uaf(struct kunit *test) { char *ptr; size_t size =3D KMALLOC_MAX_CACHE_SIZE + 10; @@ -249,7 +250,7 @@ static void kmalloc_pagealloc_uaf(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); } =20 -static void kmalloc_pagealloc_invalid_free(struct kunit *test) +static void kmalloc_large_invalid_free(struct kunit *test) { char *ptr; size_t size =3D KMALLOC_MAX_CACHE_SIZE + 10; @@ -262,7 +263,7 @@ static void kmalloc_pagealloc_invalid_free(struct kunit= *test) KUNIT_EXPECT_KASAN_FAIL(test, kfree(ptr + 1)); } =20 -static void pagealloc_oob_right(struct kunit *test) +static void page_alloc_oob_right(struct kunit *test) { char *ptr; struct page *pages; @@ -284,7 +285,7 @@ static void pagealloc_oob_right(struct kunit *test) free_pages((unsigned long)ptr, order); } =20 -static void pagealloc_uaf(struct kunit *test) +static void page_alloc_uaf(struct kunit *test) { char *ptr; struct page *pages; @@ -298,15 +299,15 @@ static void pagealloc_uaf(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); } =20 -static void kmalloc_large_oob_right(struct kunit *test) +/* + * Check that KASAN detects an out-of-bounds access for a big object alloc= ated + * via kmalloc(). But not as big as to trigger the page_alloc fallback for= SLUB. + */ +static void kmalloc_big_oob_right(struct kunit *test) { char *ptr; size_t size =3D KMALLOC_MAX_CACHE_SIZE - 256; =20 - /* - * Allocate a chunk that is large enough, but still fits into a slab - * and does not trigger the page allocator fallback in SLUB. - */ ptr =3D kmalloc(size, GFP_KERNEL); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); =20 @@ -404,18 +405,18 @@ static void krealloc_less_oob(struct kunit *test) krealloc_less_oob_helper(test, 235, 201); } =20 -static void krealloc_pagealloc_more_oob(struct kunit *test) +static void krealloc_large_more_oob(struct kunit *test) { - /* page_alloc fallback in only implemented for SLUB. */ + /* page_alloc fallback is only implemented for SLUB. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); =20 krealloc_more_oob_helper(test, KMALLOC_MAX_CACHE_SIZE + 201, KMALLOC_MAX_CACHE_SIZE + 235); } =20 -static void krealloc_pagealloc_less_oob(struct kunit *test) +static void krealloc_large_less_oob(struct kunit *test) { - /* page_alloc fallback in only implemented for SLUB. */ + /* page_alloc fallback is only implemented for SLUB. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_SLUB); =20 krealloc_less_oob_helper(test, KMALLOC_MAX_CACHE_SIZE + 235, @@ -1816,16 +1817,16 @@ static struct kunit_case kasan_kunit_test_cases[] = =3D { KUNIT_CASE(kmalloc_oob_right), KUNIT_CASE(kmalloc_oob_left), KUNIT_CASE(kmalloc_node_oob_right), - KUNIT_CASE(kmalloc_pagealloc_oob_right), - KUNIT_CASE(kmalloc_pagealloc_uaf), - KUNIT_CASE(kmalloc_pagealloc_invalid_free), - KUNIT_CASE(pagealloc_oob_right), - KUNIT_CASE(pagealloc_uaf), KUNIT_CASE(kmalloc_large_oob_right), + KUNIT_CASE(kmalloc_large_uaf), + KUNIT_CASE(kmalloc_large_invalid_free), + KUNIT_CASE(page_alloc_oob_right), + KUNIT_CASE(page_alloc_uaf), + KUNIT_CASE(kmalloc_big_oob_right), KUNIT_CASE(krealloc_more_oob), KUNIT_CASE(krealloc_less_oob), - KUNIT_CASE(krealloc_pagealloc_more_oob), - KUNIT_CASE(krealloc_pagealloc_less_oob), + KUNIT_CASE(krealloc_large_more_oob), + KUNIT_CASE(krealloc_large_less_oob), KUNIT_CASE(krealloc_uaf), KUNIT_CASE(kmalloc_oob_16), KUNIT_CASE(kmalloc_uaf_16), --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-173.mta1.migadu.com (out-173.mta1.migadu.com [95.215.58.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D1584CB2C for ; Tue, 19 Dec 2023 22:32:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="csItksj+" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025148; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JAXOX97EsAmXy2yhWR89ibBKpDRw8QdBu0qlhVLQFtk=; b=csItksj+qfVZgYztXVXmO5Q/IjIHIbtHAh6iT/j8QfAxoWkkqq3VWgkBhbzwvLM84M8D0A TY/aJpwJCMqD/cTXvUGvVm9NwUBAX39OldG7WZQHt0DozXkegxdK48FHxPlZa+KERo76WU +T7Q2BbJcPQj9yUjKW5CnW+vavcmm5s= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 18/21] kasan: reorder tests Date: Tue, 19 Dec 2023 23:29:02 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Put closely related tests next to each other. No functional changes. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- mm/kasan/kasan_test.c | 418 +++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 209 deletions(-) diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c index 230958de7604..1c77c73ff287 100644 --- a/mm/kasan/kasan_test.c +++ b/mm/kasan/kasan_test.c @@ -213,6 +213,23 @@ static void kmalloc_node_oob_right(struct kunit *test) kfree(ptr); } =20 +/* + * Check that KASAN detects an out-of-bounds access for a big object alloc= ated + * via kmalloc(). But not as big as to trigger the page_alloc fallback for= SLUB. + */ +static void kmalloc_big_oob_right(struct kunit *test) +{ + char *ptr; + size_t size =3D KMALLOC_MAX_CACHE_SIZE - 256; + + ptr =3D kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + + OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] =3D 0); + kfree(ptr); +} + /* * The kmalloc_large_* tests below use kmalloc() to allocate a memory chunk * that does not fit into the largest slab cache and therefore is allocate= d via @@ -299,23 +316,6 @@ static void page_alloc_uaf(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); } =20 -/* - * Check that KASAN detects an out-of-bounds access for a big object alloc= ated - * via kmalloc(). But not as big as to trigger the page_alloc fallback for= SLUB. - */ -static void kmalloc_big_oob_right(struct kunit *test) -{ - char *ptr; - size_t size =3D KMALLOC_MAX_CACHE_SIZE - 256; - - ptr =3D kmalloc(size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); - - OPTIMIZER_HIDE_VAR(ptr); - KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] =3D 0); - kfree(ptr); -} - static void krealloc_more_oob_helper(struct kunit *test, size_t size1, size_t size2) { @@ -698,6 +698,126 @@ static void kmalloc_uaf3(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr1)[8]); } =20 +static void kmalloc_double_kzfree(struct kunit *test) +{ + char *ptr; + size_t size =3D 16; + + ptr =3D kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + + kfree_sensitive(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr)); +} + +/* Check that ksize() does NOT unpoison whole object. */ +static void ksize_unpoisons_memory(struct kunit *test) +{ + char *ptr; + size_t size =3D 128 - KASAN_GRANULE_SIZE - 5; + size_t real_size; + + ptr =3D kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + + real_size =3D ksize(ptr); + KUNIT_EXPECT_GT(test, real_size, size); + + OPTIMIZER_HIDE_VAR(ptr); + + /* These accesses shouldn't trigger a KASAN report. */ + ptr[0] =3D 'x'; + ptr[size - 1] =3D 'x'; + + /* These must trigger a KASAN report. */ + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size + 5]); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size - 1]); + + kfree(ptr); +} + +/* + * Check that a use-after-free is detected by ksize() and via normal acces= ses + * after it. + */ +static void ksize_uaf(struct kunit *test) +{ + char *ptr; + int size =3D 128 - KASAN_GRANULE_SIZE; + + ptr =3D kmalloc(size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + kfree(ptr); + + OPTIMIZER_HIDE_VAR(ptr); + KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr)); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); + KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); +} + +/* + * The two tests below check that Generic KASAN prints auxiliary stack tra= ces + * for RCU callbacks and workqueues. The reports need to be inspected manu= ally. + * + * These tests are still enabled for other KASAN modes to make sure that a= ll + * modes report bad accesses in tested scenarios. + */ + +static struct kasan_rcu_info { + int i; + struct rcu_head rcu; +} *global_rcu_ptr; + +static void rcu_uaf_reclaim(struct rcu_head *rp) +{ + struct kasan_rcu_info *fp =3D + container_of(rp, struct kasan_rcu_info, rcu); + + kfree(fp); + ((volatile struct kasan_rcu_info *)fp)->i; +} + +static void rcu_uaf(struct kunit *test) +{ + struct kasan_rcu_info *ptr; + + ptr =3D kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + + global_rcu_ptr =3D rcu_dereference_protected( + (struct kasan_rcu_info __rcu *)ptr, NULL); + + KUNIT_EXPECT_KASAN_FAIL(test, + call_rcu(&global_rcu_ptr->rcu, rcu_uaf_reclaim); + rcu_barrier()); +} + +static void workqueue_uaf_work(struct work_struct *work) +{ + kfree(work); +} + +static void workqueue_uaf(struct kunit *test) +{ + struct workqueue_struct *workqueue; + struct work_struct *work; + + workqueue =3D create_workqueue("kasan_workqueue_test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, workqueue); + + work =3D kmalloc(sizeof(struct work_struct), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); + + INIT_WORK(work, workqueue_uaf_work); + queue_work(workqueue, work); + destroy_workqueue(workqueue); + + KUNIT_EXPECT_KASAN_FAIL(test, + ((volatile struct work_struct *)work)->data); +} + static void kfree_via_page(struct kunit *test) { char *ptr; @@ -748,6 +868,69 @@ static void kmem_cache_oob(struct kunit *test) kmem_cache_destroy(cache); } =20 +static void kmem_cache_double_free(struct kunit *test) +{ + char *p; + size_t size =3D 200; + struct kmem_cache *cache; + + cache =3D kmem_cache_create("test_cache", size, 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); + + p =3D kmem_cache_alloc(cache, GFP_KERNEL); + if (!p) { + kunit_err(test, "Allocation failed: %s\n", __func__); + kmem_cache_destroy(cache); + return; + } + + kmem_cache_free(cache, p); + KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p)); + kmem_cache_destroy(cache); +} + +static void kmem_cache_invalid_free(struct kunit *test) +{ + char *p; + size_t size =3D 200; + struct kmem_cache *cache; + + cache =3D kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU, + NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); + + p =3D kmem_cache_alloc(cache, GFP_KERNEL); + if (!p) { + kunit_err(test, "Allocation failed: %s\n", __func__); + kmem_cache_destroy(cache); + return; + } + + /* Trigger invalid free, the object doesn't get freed. */ + KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p + 1)); + + /* + * Properly free the object to prevent the "Objects remaining in + * test_cache on __kmem_cache_shutdown" BUG failure. + */ + kmem_cache_free(cache, p); + + kmem_cache_destroy(cache); +} + +static void empty_cache_ctor(void *object) { } + +static void kmem_cache_double_destroy(struct kunit *test) +{ + struct kmem_cache *cache; + + /* Provide a constructor to prevent cache merging. */ + cache =3D kmem_cache_create("test_cache", 200, 0, 0, empty_cache_ctor); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); + kmem_cache_destroy(cache); + KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_destroy(cache)); +} + static void kmem_cache_accounted(struct kunit *test) { int i; @@ -1145,53 +1328,6 @@ static void kasan_global_oob_left(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); } =20 -/* Check that ksize() does NOT unpoison whole object. */ -static void ksize_unpoisons_memory(struct kunit *test) -{ - char *ptr; - size_t size =3D 128 - KASAN_GRANULE_SIZE - 5; - size_t real_size; - - ptr =3D kmalloc(size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); - - real_size =3D ksize(ptr); - KUNIT_EXPECT_GT(test, real_size, size); - - OPTIMIZER_HIDE_VAR(ptr); - - /* These accesses shouldn't trigger a KASAN report. */ - ptr[0] =3D 'x'; - ptr[size - 1] =3D 'x'; - - /* These must trigger a KASAN report. */ - if (IS_ENABLED(CONFIG_KASAN_GENERIC)) - KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); - KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size + 5]); - KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[real_size - 1]); - - kfree(ptr); -} - -/* - * Check that a use-after-free is detected by ksize() and via normal acces= ses - * after it. - */ -static void ksize_uaf(struct kunit *test) -{ - char *ptr; - int size =3D 128 - KASAN_GRANULE_SIZE; - - ptr =3D kmalloc(size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); - kfree(ptr); - - OPTIMIZER_HIDE_VAR(ptr); - KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr)); - KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]); - KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]); -} - static void kasan_stack_oob(struct kunit *test) { char stack_array[10]; @@ -1234,69 +1370,6 @@ static void kasan_alloca_oob_right(struct kunit *tes= t) KUNIT_EXPECT_KASAN_FAIL(test, *(volatile char *)p); } =20 -static void kmem_cache_double_free(struct kunit *test) -{ - char *p; - size_t size =3D 200; - struct kmem_cache *cache; - - cache =3D kmem_cache_create("test_cache", size, 0, 0, NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); - - p =3D kmem_cache_alloc(cache, GFP_KERNEL); - if (!p) { - kunit_err(test, "Allocation failed: %s\n", __func__); - kmem_cache_destroy(cache); - return; - } - - kmem_cache_free(cache, p); - KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p)); - kmem_cache_destroy(cache); -} - -static void kmem_cache_invalid_free(struct kunit *test) -{ - char *p; - size_t size =3D 200; - struct kmem_cache *cache; - - cache =3D kmem_cache_create("test_cache", size, 0, SLAB_TYPESAFE_BY_RCU, - NULL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); - - p =3D kmem_cache_alloc(cache, GFP_KERNEL); - if (!p) { - kunit_err(test, "Allocation failed: %s\n", __func__); - kmem_cache_destroy(cache); - return; - } - - /* Trigger invalid free, the object doesn't get freed. */ - KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_free(cache, p + 1)); - - /* - * Properly free the object to prevent the "Objects remaining in - * test_cache on __kmem_cache_shutdown" BUG failure. - */ - kmem_cache_free(cache, p); - - kmem_cache_destroy(cache); -} - -static void empty_cache_ctor(void *object) { } - -static void kmem_cache_double_destroy(struct kunit *test) -{ - struct kmem_cache *cache; - - /* Provide a constructor to prevent cache merging. */ - cache =3D kmem_cache_create("test_cache", 200, 0, 0, empty_cache_ctor); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cache); - kmem_cache_destroy(cache); - KUNIT_EXPECT_KASAN_FAIL(test, kmem_cache_destroy(cache)); -} - static void kasan_memchr(struct kunit *test) { char *ptr; @@ -1458,79 +1531,6 @@ static void kasan_bitops_tags(struct kunit *test) kfree(bits); } =20 -static void kmalloc_double_kzfree(struct kunit *test) -{ - char *ptr; - size_t size =3D 16; - - ptr =3D kmalloc(size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); - - kfree_sensitive(ptr); - KUNIT_EXPECT_KASAN_FAIL(test, kfree_sensitive(ptr)); -} - -/* - * The two tests below check that Generic KASAN prints auxiliary stack tra= ces - * for RCU callbacks and workqueues. The reports need to be inspected manu= ally. - * - * These tests are still enabled for other KASAN modes to make sure that a= ll - * modes report bad accesses in tested scenarios. - */ - -static struct kasan_rcu_info { - int i; - struct rcu_head rcu; -} *global_rcu_ptr; - -static void rcu_uaf_reclaim(struct rcu_head *rp) -{ - struct kasan_rcu_info *fp =3D - container_of(rp, struct kasan_rcu_info, rcu); - - kfree(fp); - ((volatile struct kasan_rcu_info *)fp)->i; -} - -static void rcu_uaf(struct kunit *test) -{ - struct kasan_rcu_info *ptr; - - ptr =3D kmalloc(sizeof(struct kasan_rcu_info), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); - - global_rcu_ptr =3D rcu_dereference_protected( - (struct kasan_rcu_info __rcu *)ptr, NULL); - - KUNIT_EXPECT_KASAN_FAIL(test, - call_rcu(&global_rcu_ptr->rcu, rcu_uaf_reclaim); - rcu_barrier()); -} - -static void workqueue_uaf_work(struct work_struct *work) -{ - kfree(work); -} - -static void workqueue_uaf(struct kunit *test) -{ - struct workqueue_struct *workqueue; - struct work_struct *work; - - workqueue =3D create_workqueue("kasan_workqueue_test"); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, workqueue); - - work =3D kmalloc(sizeof(struct work_struct), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work); - - INIT_WORK(work, workqueue_uaf_work); - queue_work(workqueue, work); - destroy_workqueue(workqueue); - - KUNIT_EXPECT_KASAN_FAIL(test, - ((volatile struct work_struct *)work)->data); -} - static void vmalloc_helpers_tags(struct kunit *test) { void *ptr; @@ -1817,12 +1817,12 @@ static struct kunit_case kasan_kunit_test_cases[] = =3D { KUNIT_CASE(kmalloc_oob_right), KUNIT_CASE(kmalloc_oob_left), KUNIT_CASE(kmalloc_node_oob_right), + KUNIT_CASE(kmalloc_big_oob_right), KUNIT_CASE(kmalloc_large_oob_right), KUNIT_CASE(kmalloc_large_uaf), KUNIT_CASE(kmalloc_large_invalid_free), KUNIT_CASE(page_alloc_oob_right), KUNIT_CASE(page_alloc_uaf), - KUNIT_CASE(kmalloc_big_oob_right), KUNIT_CASE(krealloc_more_oob), KUNIT_CASE(krealloc_less_oob), KUNIT_CASE(krealloc_large_more_oob), @@ -1841,9 +1841,17 @@ static struct kunit_case kasan_kunit_test_cases[] = =3D { KUNIT_CASE(kmalloc_uaf_memset), KUNIT_CASE(kmalloc_uaf2), KUNIT_CASE(kmalloc_uaf3), + KUNIT_CASE(kmalloc_double_kzfree), + KUNIT_CASE(ksize_unpoisons_memory), + KUNIT_CASE(ksize_uaf), + KUNIT_CASE(rcu_uaf), + KUNIT_CASE(workqueue_uaf), KUNIT_CASE(kfree_via_page), KUNIT_CASE(kfree_via_phys), KUNIT_CASE(kmem_cache_oob), + KUNIT_CASE(kmem_cache_double_free), + KUNIT_CASE(kmem_cache_invalid_free), + KUNIT_CASE(kmem_cache_double_destroy), KUNIT_CASE(kmem_cache_accounted), KUNIT_CASE(kmem_cache_bulk), KUNIT_CASE(mempool_kmalloc_oob_right), @@ -1863,19 +1871,11 @@ static struct kunit_case kasan_kunit_test_cases[] = =3D { KUNIT_CASE(kasan_stack_oob), KUNIT_CASE(kasan_alloca_oob_left), KUNIT_CASE(kasan_alloca_oob_right), - KUNIT_CASE(ksize_unpoisons_memory), - KUNIT_CASE(ksize_uaf), - KUNIT_CASE(kmem_cache_double_free), - KUNIT_CASE(kmem_cache_invalid_free), - KUNIT_CASE(kmem_cache_double_destroy), KUNIT_CASE(kasan_memchr), KUNIT_CASE(kasan_memcmp), KUNIT_CASE(kasan_strings), KUNIT_CASE(kasan_bitops_generic), KUNIT_CASE(kasan_bitops_tags), - KUNIT_CASE(kmalloc_double_kzfree), - KUNIT_CASE(rcu_uaf), - KUNIT_CASE(workqueue_uaf), KUNIT_CASE(vmalloc_helpers_tags), KUNIT_CASE(vmalloc_oob), KUNIT_CASE(vmap_tags), --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-182.mta1.migadu.com (out-182.mta1.migadu.com [95.215.58.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 597B64CB43 for ; Tue, 19 Dec 2023 22:32:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="bmAVzIYf" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025149; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mlYQJh3Zrut4xXu3wLWLs7KGtUj3CeTDuDfdtjdzU7g=; b=bmAVzIYfyYppWmvGTLBiS5nG8obTrmbbdL0D6+ClOLIyRzStyC0cUpgaQoGRj4B9negloZ gDBuxMa0ozyhE+nyywcFc4sF3IFTOtfxFhASYlhLoyPMu0p611lKZY7InRWt+SuofDu71+ 8EC/bvZUjw4CO1A7j3BBvX7vr2/bJog= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 19/21] kasan: rename and document kasan_(un)poison_object_data Date: Tue, 19 Dec 2023 23:29:03 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Rename kasan_unpoison_object_data to kasan_unpoison_new_object and add a documentation comment. Do the same for kasan_poison_object_data. The new names and the comments should suggest the users that these hooks are intended for internal use by the slab allocator. The following patch will remove non-slab-internal uses of these hooks. No functional changes. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- include/linux/kasan.h | 35 +++++++++++++++++++++++++++-------- mm/kasan/common.c | 4 ++-- mm/slab.c | 10 ++++------ mm/slub.c | 4 ++-- net/core/skbuff.c | 8 ++++---- 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 7392c5d89b92..d49e3d4c099e 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -129,20 +129,39 @@ static __always_inline void kasan_poison_slab(struct = slab *slab) __kasan_poison_slab(slab); } =20 -void __kasan_unpoison_object_data(struct kmem_cache *cache, void *object); -static __always_inline void kasan_unpoison_object_data(struct kmem_cache *= cache, +void __kasan_unpoison_new_object(struct kmem_cache *cache, void *object); +/** + * kasan_unpoison_new_object - Temporarily unpoison a new slab object. + * @cache: Cache the object belong to. + * @object: Pointer to the object. + * + * This function is intended for the slab allocator's internal use. It + * temporarily unpoisons an object from a newly allocated slab without doi= ng + * anything else. The object must later be repoisoned by + * kasan_poison_new_object(). + */ +static __always_inline void kasan_unpoison_new_object(struct kmem_cache *c= ache, void *object) { if (kasan_enabled()) - __kasan_unpoison_object_data(cache, object); + __kasan_unpoison_new_object(cache, object); } =20 -void __kasan_poison_object_data(struct kmem_cache *cache, void *object); -static __always_inline void kasan_poison_object_data(struct kmem_cache *ca= che, +void __kasan_poison_new_object(struct kmem_cache *cache, void *object); +/** + * kasan_unpoison_new_object - Repoison a new slab object. + * @cache: Cache the object belong to. + * @object: Pointer to the object. + * + * This function is intended for the slab allocator's internal use. It + * repoisons an object that was previously unpoisoned by + * kasan_unpoison_new_object() without doing anything else. + */ +static __always_inline void kasan_poison_new_object(struct kmem_cache *cac= he, void *object) { if (kasan_enabled()) - __kasan_poison_object_data(cache, object); + __kasan_poison_new_object(cache, object); } =20 void * __must_check __kasan_init_slab_obj(struct kmem_cache *cache, @@ -342,9 +361,9 @@ static inline bool kasan_unpoison_pages(struct page *pa= ge, unsigned int order, return false; } static inline void kasan_poison_slab(struct slab *slab) {} -static inline void kasan_unpoison_object_data(struct kmem_cache *cache, +static inline void kasan_unpoison_new_object(struct kmem_cache *cache, void *object) {} -static inline void kasan_poison_object_data(struct kmem_cache *cache, +static inline void kasan_poison_new_object(struct kmem_cache *cache, void *object) {} static inline void *kasan_init_slab_obj(struct kmem_cache *cache, const void *object) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index b8e7416f83af..ebb1b23d6480 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -143,12 +143,12 @@ void __kasan_poison_slab(struct slab *slab) KASAN_SLAB_REDZONE, false); } =20 -void __kasan_unpoison_object_data(struct kmem_cache *cache, void *object) +void __kasan_unpoison_new_object(struct kmem_cache *cache, void *object) { kasan_unpoison(object, cache->object_size, false); } =20 -void __kasan_poison_object_data(struct kmem_cache *cache, void *object) +void __kasan_poison_new_object(struct kmem_cache *cache, void *object) { kasan_poison(object, round_up(cache->object_size, KASAN_GRANULE_SIZE), KASAN_SLAB_REDZONE, false); diff --git a/mm/slab.c b/mm/slab.c index 9ad3d0f2d1a5..773c79e153f3 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2327,11 +2327,9 @@ static void cache_init_objs_debug(struct kmem_cache = *cachep, struct slab *slab) * They must also be threaded. */ if (cachep->ctor && !(cachep->flags & SLAB_POISON)) { - kasan_unpoison_object_data(cachep, - objp + obj_offset(cachep)); + kasan_unpoison_new_object(cachep, objp + obj_offset(cachep)); cachep->ctor(objp + obj_offset(cachep)); - kasan_poison_object_data( - cachep, objp + obj_offset(cachep)); + kasan_poison_new_object(cachep, objp + obj_offset(cachep)); } =20 if (cachep->flags & SLAB_RED_ZONE) { @@ -2472,9 +2470,9 @@ static void cache_init_objs(struct kmem_cache *cachep, =20 /* constructor could break poison info */ if (DEBUG =3D=3D 0 && cachep->ctor) { - kasan_unpoison_object_data(cachep, objp); + kasan_unpoison_new_object(cachep, objp); cachep->ctor(objp); - kasan_poison_object_data(cachep, objp); + kasan_poison_new_object(cachep, objp); } =20 if (!shuffled) diff --git a/mm/slub.c b/mm/slub.c index 782bd8a6bd34..891742e5932a 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1860,9 +1860,9 @@ static void *setup_object(struct kmem_cache *s, void = *object) setup_object_debug(s, object); object =3D kasan_init_slab_obj(s, object); if (unlikely(s->ctor)) { - kasan_unpoison_object_data(s, object); + kasan_unpoison_new_object(s, object); s->ctor(object); - kasan_poison_object_data(s, object); + kasan_poison_new_object(s, object); } return object; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b157efea5dea..63bb6526399d 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -337,7 +337,7 @@ static struct sk_buff *napi_skb_cache_get(void) } =20 skb =3D nc->skb_cache[--nc->skb_count]; - kasan_unpoison_object_data(skbuff_cache, skb); + kasan_unpoison_new_object(skbuff_cache, skb); =20 return skb; } @@ -1309,13 +1309,13 @@ static void napi_skb_cache_put(struct sk_buff *skb) struct napi_alloc_cache *nc =3D this_cpu_ptr(&napi_alloc_cache); u32 i; =20 - kasan_poison_object_data(skbuff_cache, skb); + kasan_poison_new_object(skbuff_cache, skb); nc->skb_cache[nc->skb_count++] =3D skb; =20 if (unlikely(nc->skb_count =3D=3D NAPI_SKB_CACHE_SIZE)) { for (i =3D NAPI_SKB_CACHE_HALF; i < NAPI_SKB_CACHE_SIZE; i++) - kasan_unpoison_object_data(skbuff_cache, - nc->skb_cache[i]); + kasan_unpoison_new_object(skbuff_cache, + nc->skb_cache[i]); =20 kmem_cache_free_bulk(skbuff_cache, NAPI_SKB_CACHE_HALF, nc->skb_cache + NAPI_SKB_CACHE_HALF); --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-189.mta1.migadu.com (out-189.mta1.migadu.com [95.215.58.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03BEB4CB22 for ; Tue, 19 Dec 2023 22:32:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ljf0/KaK" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025149; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=e29xpsueqsta+pB4dpMwNezQWpITpFZrOcR7dgpqXnM=; b=ljf0/KaKFmDC2Uyj9pcq18seQDB62a/kgliZneYzRVKag4kgTWvduY54lnptev/4IOVTKg XWh9fADptQruk8bYRvzl+jF0l8p4U0RNpQ3xZT3+C7DxlLuZnVWmBR0/EtI5V5z/V058ga q4EXpOfTgh0O1XTzevXYooHK4dHrhlQ= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 20/21] skbuff: use mempool KASAN hooks Date: Tue, 19 Dec 2023 23:29:04 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Instead of using slab-internal KASAN hooks for poisoning and unpoisoning cached objects, use the proper mempool KASAN hooks. Also check the return value of kasan_mempool_poison_object to prevent double-free and invali-free bugs. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- net/core/skbuff.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 63bb6526399d..bb75b4272992 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -337,7 +337,7 @@ static struct sk_buff *napi_skb_cache_get(void) } =20 skb =3D nc->skb_cache[--nc->skb_count]; - kasan_unpoison_new_object(skbuff_cache, skb); + kasan_mempool_unpoison_object(skb, kmem_cache_size(skbuff_cache)); =20 return skb; } @@ -1309,13 +1309,15 @@ static void napi_skb_cache_put(struct sk_buff *skb) struct napi_alloc_cache *nc =3D this_cpu_ptr(&napi_alloc_cache); u32 i; =20 - kasan_poison_new_object(skbuff_cache, skb); + if (!kasan_mempool_poison_object(skb)) + return; + nc->skb_cache[nc->skb_count++] =3D skb; =20 if (unlikely(nc->skb_count =3D=3D NAPI_SKB_CACHE_SIZE)) { for (i =3D NAPI_SKB_CACHE_HALF; i < NAPI_SKB_CACHE_SIZE; i++) - kasan_unpoison_new_object(skbuff_cache, - nc->skb_cache[i]); + kasan_mempool_unpoison_object(nc->skb_cache[i], + kmem_cache_size(skbuff_cache)); =20 kmem_cache_free_bulk(skbuff_cache, NAPI_SKB_CACHE_HALF, nc->skb_cache + NAPI_SKB_CACHE_HALF); --=20 2.25.1 From nobody Fri Dec 19 12:28:19 2025 Received: from out-189.mta1.migadu.com (out-189.mta1.migadu.com [95.215.58.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C8C54CB34 for ; Tue, 19 Dec 2023 22:32:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="PVS7/Vp9" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703025150; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EPGVjwO+qP/d7FcuwPK2D6CcDKWjvT42oG4AsVrb0Go=; b=PVS7/Vp9rKcCStvahkmREEOMnuEX6kau1z/8KUeJ+M+L9oh0S/muURork3hPcDgoR/5lvV ReB2LpYutwX5p3c63FdFGnocPloJeeIBz+IrzYNEY41q/t2SiRz0dp5ZLm4EF8f/mEHnF3 IzsuSBbMxsPovIvvYoBbisxMLMXLZwo= From: andrey.konovalov@linux.dev To: Marco Elver , Alexander Potapenko Cc: Andrey Konovalov , Dmitry Vyukov , Andrey Ryabinin , kasan-dev@googlegroups.com, Evgenii Stepanov , Breno Leitao , Alexander Lobakin , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov Subject: [PATCH mm 21/21] io_uring: use mempool KASAN hook Date: Tue, 19 Dec 2023 23:29:05 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Andrey Konovalov Use the proper kasan_mempool_unpoison_object hook for unpoisoning cached objects. A future change might also update io_uring to check the return value of kasan_mempool_poison_object to prevent double-free and invalid-free bugs. This proves to be non-trivial with the current way io_uring caches objects, so this is left out-of-scope of this series. Signed-off-by: Andrey Konovalov Acked-by: Marco Elver --- io_uring/alloc_cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_uring/alloc_cache.h b/io_uring/alloc_cache.h index 8de0414e8efe..bf2fb26a6539 100644 --- a/io_uring/alloc_cache.h +++ b/io_uring/alloc_cache.h @@ -33,7 +33,7 @@ static inline struct io_cache_entry *io_alloc_cache_get(s= truct io_alloc_cache *c struct io_cache_entry *entry; =20 entry =3D container_of(cache->list.next, struct io_cache_entry, node); - kasan_unpoison_range(entry, cache->elem_size); + kasan_mempool_unpoison_object(entry, cache->elem_size); cache->list.next =3D cache->list.next->next; cache->nr_cached--; return entry; --=20 2.25.1