mm: new primitive kvmemdup()
Similar to kmemdup(), but support large amount of bytes with kvmalloc() and does *not* guarantee that the result will be physically contiguous. Use only in cases where kvmalloc() is needed and free it with kvfree(). Also adapt policy_unpack.c in case someone bisect into this. Link: https://lkml.kernel.org/r/20221221144245.27164-1-sunhao.th@gmail.com Signed-off-by: Hao Sun <sunhao.th@gmail.com> Suggested-by: Daniel Borkmann <daniel@iogearbox.net> Cc: Nick Terrell <terrelln@fb.com> Cc: John Johansen <john.johansen@canonical.com> Cc: Paul Moore <paul@paul-moore.com> Cc: James Morris <jmorris@namei.org> Cc: "Serge E. Hallyn" <serge@hallyn.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
5a9e34747c
commit
0b7b8704dd
|
@ -177,6 +177,7 @@ extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
|
|||
extern const char *kstrdup_const(const char *s, gfp_t gfp);
|
||||
extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
|
||||
extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
|
||||
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 char **argv_split(gfp_t gfp, const char *str, int *argcp);
|
||||
|
|
24
mm/util.c
24
mm/util.c
|
@ -120,7 +120,8 @@ EXPORT_SYMBOL(kstrndup);
|
|||
* @len: memory region length
|
||||
* @gfp: GFP mask to use
|
||||
*
|
||||
* Return: newly allocated copy of @src or %NULL in case of error
|
||||
* Return: newly allocated copy of @src or %NULL in case of error,
|
||||
* result is physically contiguous. Use kfree() to free.
|
||||
*/
|
||||
void *kmemdup(const void *src, size_t len, gfp_t gfp)
|
||||
{
|
||||
|
@ -133,6 +134,27 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
|
|||
}
|
||||
EXPORT_SYMBOL(kmemdup);
|
||||
|
||||
/**
|
||||
* kvmemdup - duplicate region of memory
|
||||
*
|
||||
* @src: memory region to duplicate
|
||||
* @len: memory region length
|
||||
* @gfp: GFP mask to use
|
||||
*
|
||||
* Return: newly allocated copy of @src or %NULL in case of error,
|
||||
* result may be not physically contiguous. Use kvfree() to free.
|
||||
*/
|
||||
void *kvmemdup(const void *src, size_t len, gfp_t gfp)
|
||||
{
|
||||
void *p;
|
||||
|
||||
p = kvmalloc(len, gfp);
|
||||
if (p)
|
||||
memcpy(p, src, len);
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(kvmemdup);
|
||||
|
||||
/**
|
||||
* kmemdup_nul - Create a NUL-terminated string from unterminated data
|
||||
* @s: The data to stringify
|
||||
|
|
|
@ -161,15 +161,6 @@ VISIBLE_IF_KUNIT bool aa_inbounds(struct aa_ext *e, size_t size)
|
|||
}
|
||||
EXPORT_SYMBOL_IF_KUNIT(aa_inbounds);
|
||||
|
||||
static void *kvmemdup(const void *src, size_t len)
|
||||
{
|
||||
void *p = kvmalloc(len, GFP_KERNEL);
|
||||
|
||||
if (p)
|
||||
memcpy(p, src, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_unpack_u16_chunk - test and do bounds checking for a u16 size based chunk
|
||||
* @e: serialized data read head (NOT NULL)
|
||||
|
@ -1027,7 +1018,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
|
|||
|
||||
data->key = key;
|
||||
data->size = aa_unpack_blob(e, &data->data, NULL);
|
||||
data->data = kvmemdup(data->data, data->size);
|
||||
data->data = kvmemdup(data->data, data->size, GFP_KERNEL);
|
||||
if (data->size && !data->data) {
|
||||
kfree_sensitive(data->key);
|
||||
kfree_sensitive(data);
|
||||
|
|
Loading…
Reference in New Issue