* [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