linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO
@ 2024-08-12 22:34 Danilo Krummrich
  2024-08-12 22:34 ` [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO Danilo Krummrich
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Danilo Krummrich @ 2024-08-12 22:34 UTC (permalink / raw)
  To: akpm, cl, penberg, rientjes, iamjoonsoo.kim, vbabka,
	roman.gushchin, 42.hyeyoo
  Cc: linux-kernel, linux-mm, Danilo Krummrich

As long as krealloc() is called with __GFP_ZERO consistently, starting
with the initial memory allocation, __GFP_ZERO should be fully honored.

However, if for an existing allocation krealloc() is called with a
decreased size, it is not ensured that the spare portion the allocation
is zeroed. Thus, if krealloc() is subsequently called with a larger size
again, __GFP_ZERO can't be fully honored, since we don't know the
previous size, but only the bucket size.

Example:

	buf = kzalloc(64, GFP_KERNEL);
	memset(buf, 0xff, 64);

	buf = krealloc(buf, 48, GFP_KERNEL | __GFP_ZERO);

	/* After this call the last 16 bytes are still 0xff. */
	buf = krealloc(buf, 64, GFP_KERNEL | __GFP_ZERO);

Fix this, by explicitly setting spare memory to zero, when shrinking an
allocation with __GFP_ZERO flag set or init_on_alloc enabled.

Acked-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
 mm/slab_common.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/mm/slab_common.c b/mm/slab_common.c
index 40b582a014b8..cff602cedf8e 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1273,6 +1273,13 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags)
 
 	/* If the object still fits, repoison it precisely. */
 	if (ks >= new_size) {
+		/* Zero out spare memory. */
+		if (want_init_on_alloc(flags)) {
+			kasan_disable_current();
+			memset((void *)p + new_size, 0, ks - new_size);
+			kasan_enable_current();
+		}
+
 		p = kasan_krealloc((void *)p, new_size, flags);
 		return (void *)p;
 	}

base-commit: b8dbbb7fe1db26c450a9d2c3302013154b3431df
-- 
2.46.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO
  2024-08-12 22:34 [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO Danilo Krummrich
@ 2024-08-12 22:34 ` Danilo Krummrich
  2024-08-13  2:32   ` David Rientjes
  2024-08-13  2:32 ` [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO David Rientjes
  2024-08-19 23:23 ` Danilo Krummrich
  2 siblings, 1 reply; 5+ messages in thread
From: Danilo Krummrich @ 2024-08-12 22:34 UTC (permalink / raw)
  To: akpm, cl, penberg, rientjes, iamjoonsoo.kim, vbabka,
	roman.gushchin, 42.hyeyoo
  Cc: linux-kernel, linux-mm, Danilo Krummrich

Properly document that if __GFP_ZERO logic is requested, callers must
ensure that, starting with the initial memory allocation, every
subsequent call to this API for the same memory allocation is flagged
with __GFP_ZERO. Otherwise, it is possible that __GFP_ZERO is not fully
honored by this API.

Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
Changes in v2:
 - additionally to what we require callers to do, briefly explain what the
   implementation does (Andrew)
---
 include/linux/slab.h | 10 ++++++++++
 mm/slab_common.c     | 20 ++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index c9cb42203183..2282e67a01c7 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -733,6 +733,16 @@ static inline __alloc_size(1, 2) void *kmalloc_array_noprof(size_t n, size_t siz
  * @new_n: new number of elements to alloc
  * @new_size: new size of a single member of the array
  * @flags: the type of memory to allocate (see kmalloc)
+ *
+ * If __GFP_ZERO logic is requested, callers must ensure that, starting with the
+ * initial memory allocation, every subsequent call to this API for the same
+ * memory allocation is flagged with __GFP_ZERO. Otherwise, it is possible that
+ * __GFP_ZERO is not fully honored by this API.
+ *
+ * See krealloc_noprof() for further details.
+ *
+ * In any case, the contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.
  */
 static inline __realloc_size(2, 3) void * __must_check krealloc_array_noprof(void *p,
 								       size_t new_n,
diff --git a/mm/slab_common.c b/mm/slab_common.c
index cff602cedf8e..1b380eb3b4f2 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -1301,11 +1301,27 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags)
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
  *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes (__GFP_ZERO flag is effectively ignored).
  * If @p is %NULL, krealloc() behaves exactly like kmalloc().  If @new_size
  * is 0 and @p is not a %NULL pointer, the object pointed to is freed.
  *
+ * If __GFP_ZERO logic is requested, callers must ensure that, starting with the
+ * initial memory allocation, every subsequent call to this API for the same
+ * memory allocation is flagged with __GFP_ZERO. Otherwise, it is possible that
+ * __GFP_ZERO is not fully honored by this API.
+ *
+ * This is the case, since krealloc() only knows about the bucket size of an
+ * allocation (but not the exact size it was allocated with) and hence
+ * implements the following semantics for shrinking and growing buffers with
+ * __GFP_ZERO.
+ *
+ *         new             bucket
+ * 0       size             size
+ * |--------|----------------|
+ * |  keep  |      zero      |
+ *
+ * In any case, the contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.
+ *
  * Return: pointer to the allocated memory or %NULL in case of error
  */
 void *krealloc_noprof(const void *p, size_t new_size, gfp_t flags)
-- 
2.46.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO
  2024-08-12 22:34 [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO Danilo Krummrich
  2024-08-12 22:34 ` [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO Danilo Krummrich
@ 2024-08-13  2:32 ` David Rientjes
  2024-08-19 23:23 ` Danilo Krummrich
  2 siblings, 0 replies; 5+ messages in thread
From: David Rientjes @ 2024-08-13  2:32 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: akpm, cl, penberg, iamjoonsoo.kim, vbabka, roman.gushchin,
	42.hyeyoo, linux-kernel, linux-mm

On Tue, 13 Aug 2024, Danilo Krummrich wrote:

> As long as krealloc() is called with __GFP_ZERO consistently, starting
> with the initial memory allocation, __GFP_ZERO should be fully honored.
> 
> However, if for an existing allocation krealloc() is called with a
> decreased size, it is not ensured that the spare portion the allocation
> is zeroed. Thus, if krealloc() is subsequently called with a larger size
> again, __GFP_ZERO can't be fully honored, since we don't know the
> previous size, but only the bucket size.
> 
> Example:
> 
> 	buf = kzalloc(64, GFP_KERNEL);
> 	memset(buf, 0xff, 64);
> 
> 	buf = krealloc(buf, 48, GFP_KERNEL | __GFP_ZERO);
> 
> 	/* After this call the last 16 bytes are still 0xff. */
> 	buf = krealloc(buf, 64, GFP_KERNEL | __GFP_ZERO);
> 
> Fix this, by explicitly setting spare memory to zero, when shrinking an
> allocation with __GFP_ZERO flag set or init_on_alloc enabled.
> 
> Acked-by: Vlastimil Babka <vbabka@suse.cz>
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>

Acked-by: David Rientjes <rientjes@google.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO
  2024-08-12 22:34 ` [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO Danilo Krummrich
@ 2024-08-13  2:32   ` David Rientjes
  0 siblings, 0 replies; 5+ messages in thread
From: David Rientjes @ 2024-08-13  2:32 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: akpm, cl, penberg, iamjoonsoo.kim, vbabka, roman.gushchin,
	42.hyeyoo, linux-kernel, linux-mm

On Tue, 13 Aug 2024, Danilo Krummrich wrote:

> Properly document that if __GFP_ZERO logic is requested, callers must
> ensure that, starting with the initial memory allocation, every
> subsequent call to this API for the same memory allocation is flagged
> with __GFP_ZERO. Otherwise, it is possible that __GFP_ZERO is not fully
> honored by this API.
> 
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>

Acked-by: David Rientjes <rientjes@google.com>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO
  2024-08-12 22:34 [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO Danilo Krummrich
  2024-08-12 22:34 ` [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO Danilo Krummrich
  2024-08-13  2:32 ` [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO David Rientjes
@ 2024-08-19 23:23 ` Danilo Krummrich
  2 siblings, 0 replies; 5+ messages in thread
From: Danilo Krummrich @ 2024-08-19 23:23 UTC (permalink / raw)
  To: akpm
  Cc: cl, penberg, rientjes, iamjoonsoo.kim, vbabka, roman.gushchin,
	42.hyeyoo, linux-kernel, linux-mm

On 8/13/24 12:34 AM, Danilo Krummrich wrote:

Gentle reminder on this one.

> As long as krealloc() is called with __GFP_ZERO consistently, starting
> with the initial memory allocation, __GFP_ZERO should be fully honored.
> 
> However, if for an existing allocation krealloc() is called with a
> decreased size, it is not ensured that the spare portion the allocation
> is zeroed. Thus, if krealloc() is subsequently called with a larger size
> again, __GFP_ZERO can't be fully honored, since we don't know the
> previous size, but only the bucket size.
> 
> Example:
> 
> 	buf = kzalloc(64, GFP_KERNEL);
> 	memset(buf, 0xff, 64);
> 
> 	buf = krealloc(buf, 48, GFP_KERNEL | __GFP_ZERO);
> 
> 	/* After this call the last 16 bytes are still 0xff. */
> 	buf = krealloc(buf, 64, GFP_KERNEL | __GFP_ZERO);
> 
> Fix this, by explicitly setting spare memory to zero, when shrinking an
> allocation with __GFP_ZERO flag set or init_on_alloc enabled.
> 
> Acked-by: Vlastimil Babka <vbabka@suse.cz>
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>

I think I forgot to add:

Cc: stable@vger.kernel.org

Not sure if there is a useful commit for "Fixes" though. AFAICT, this has been 
broken since forever.

> ---
>   mm/slab_common.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> index 40b582a014b8..cff602cedf8e 100644
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -1273,6 +1273,13 @@ __do_krealloc(const void *p, size_t new_size, gfp_t flags)
>   
>   	/* If the object still fits, repoison it precisely. */
>   	if (ks >= new_size) {
> +		/* Zero out spare memory. */
> +		if (want_init_on_alloc(flags)) {
> +			kasan_disable_current();
> +			memset((void *)p + new_size, 0, ks - new_size);
> +			kasan_enable_current();
> +		}
> +
>   		p = kasan_krealloc((void *)p, new_size, flags);
>   		return (void *)p;
>   	}
> 
> base-commit: b8dbbb7fe1db26c450a9d2c3302013154b3431df


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-08-19 23:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-12 22:34 [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO Danilo Krummrich
2024-08-12 22:34 ` [PATCH v2 2/2] mm: krealloc: clarify valid usage of __GFP_ZERO Danilo Krummrich
2024-08-13  2:32   ` David Rientjes
2024-08-13  2:32 ` [PATCH v2 1/2] mm: krealloc: consider spare memory for __GFP_ZERO David Rientjes
2024-08-19 23:23 ` Danilo Krummrich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox