From: Bartosz Golaszewski <bartosz.golaszew...@linaro.org> Provide a function similar to strdup_const() but for copying blocks of memory that are likely to be placed in .rodata.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszew...@linaro.org> --- include/linux/string.h | 1 + mm/util.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index fdd3442c6bcbd786e177b6e87358e1065a0ffafc..1a86d61de91204563e4179938c4dfc77108e03aa 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -304,6 +304,7 @@ extern char *kstrndup(const char *s, size_t len, gfp_t gfp); extern void *kmemdup_noprof(const void *src, size_t len, gfp_t gfp) __realloc_size(2); #define kmemdup(...) alloc_hooks(kmemdup_noprof(__VA_ARGS__)) +extern const void *kmemdup_const(const void *src, size_t len, gfp_t gfp); extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); extern void *kmemdup_array(const void *src, size_t count, size_t element_size, gfp_t gfp) diff --git a/mm/util.c b/mm/util.c index f814e6a59ab1d354b8cd04ebf3903626f6b23a6c..f4df9194b0c69c27ff06e6ba1d1137c559035470 100644 --- a/mm/util.c +++ b/mm/util.c @@ -142,6 +142,27 @@ void *kmemdup_noprof(const void *src, size_t len, gfp_t gfp) } EXPORT_SYMBOL(kmemdup_noprof); +/** + * kmemdup_const - conditionally duplicate a region of memory + * + * @src: memory region to duplicate + * @len: memory region length, + * @gfp: GFP mask to use + * + * Return: source address if it is in .rodata or the return value of kmemdup() + * to which the function falls back otherwise. + * + * Note: the returned address must not be passed to kfree(), the caller must + * use kfree_const() instead. + */ +const void *kmemdup_const(const void *src, size_t len, gfp_t gfp) +{ + if (is_kernel_rodata((unsigned long)src)) + return src; + + return kmemdup(src, len, gfp); +} + /** * kmemdup_array - duplicate a given array. * -- 2.48.1