On Tue, 30 Jul 2024 21:42:05 +0200 Danilo Krummrich <dakr@xxxxxxxxxx> 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. Well that's bad. > Example: > > buf = kzalloc(64, GFP_KERNEL); If this was kmalloc() > 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); then this would expose uninitialized kernel memory to kernel code, with a risk that the kernel code will expose that to userspace, yes? This does seem rather a trap, and I wonder whether krealloc() should just zero out any such data by default. > Fix this, by explicitly setting spare memory to zero, when shrinking an > allocation with __GFP_ZERO flag set or init_on_alloc enabled. > > --- 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); Casting away the constness of `*p'. This is just misleading everyone, really. It would be better to make argument `p' have type "void *". > + kasan_enable_current(); > + } > + > p = kasan_krealloc((void *)p, new_size, flags);