On Thu, Jul 18, 2024 at 12:24:01AM +0200, Danilo Krummrich wrote: > Implement vrealloc() analogous to krealloc(). > > Currently, krealloc() requires the caller to pass the size of the > previous memory allocation, which, instead, should be self-contained. > > We attempt to fix this in a subsequent patch which, in order to do so, > requires vrealloc(). > > Besides that, we need realloc() functions for kernel allocators in Rust > too. With `Vec` or `KVec` respectively, potentially growing (and > shrinking) data structures are rather common. > > Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx> > --- > include/linux/vmalloc.h | 4 +++ > mm/vmalloc.c | 58 +++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 62 insertions(+) > > diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h > index e4a631ec430b..9ff0a8e5c323 100644 > --- a/include/linux/vmalloc.h > +++ b/include/linux/vmalloc.h > @@ -189,6 +189,10 @@ extern void *__vcalloc_noprof(size_t n, size_t size, gfp_t flags) __alloc_size(1 > extern void *vcalloc_noprof(size_t n, size_t size) __alloc_size(1, 2); > #define vcalloc(...) alloc_hooks(vcalloc_noprof(__VA_ARGS__)) > > +extern void * __must_check vrealloc_noprof(const void *p, size_t size, > + gfp_t flags) __realloc_size(2); > +#define vrealloc(...) alloc_hooks(vrealloc_noprof(__VA_ARGS__)) > + > extern void vfree(const void *addr); > extern void vfree_atomic(const void *addr); > > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > index e34ea860153f..4ec949ac9d9d 100644 > --- a/mm/vmalloc.c > +++ b/mm/vmalloc.c > @@ -4036,6 +4036,64 @@ void *vzalloc_node_noprof(unsigned long size, int node) > } > EXPORT_SYMBOL(vzalloc_node_noprof); > > +/** > + * vrealloc - reallocate virtually contiguous memory; contents remain unchanged > + * @p: object to reallocate memory for > + * @size: the size to reallocate > + * @flags: the flags for the page level allocator > + * > + * The contents of the object pointed to are preserved up to the lesser of the > + * new and old size (__GFP_ZERO flag is effectively ignored). > + * > + * If @p is %NULL, vrealloc() behaves exactly like vmalloc(). If @size is 0 and > + * @p is not a %NULL pointer, the object pointed to is freed. > + * > + * Return: pointer to the allocated memory; %NULL if @size is zero or in case of > + * failure > + */ > +void *vrealloc_noprof(const void *p, size_t size, gfp_t flags) > +{ > + size_t old_size = 0; > + void *n; > + > + if (!size) { > + vfree(p); > + return NULL; > + } > + > + if (p) { > + struct vm_struct *vm; > + > + vm = find_vm_area(p); > Concurrent vfree() will lead to use-after-free. Either add a comment that a user is responsible for not using vrealloc()/vfree() on the same pointer concurrently or use find_unlink_vmap_area() which might be more complex when it comes to design of the vrealloc(). -- Uladzislau Rezki