Message ID | 20240812223707.32049-1-dakr@kernel.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v2,1/2] mm: krealloc: consider spare memory for __GFP_ZERO | expand |
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>
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
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; }