Skip to content

Commit 0b7b870

Browse files
SunHao-0akpm00
authored andcommitted
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/[email protected] Signed-off-by: Hao Sun <[email protected]> Suggested-by: Daniel Borkmann <[email protected]> Cc: Nick Terrell <[email protected]> Cc: John Johansen <[email protected]> Cc: Paul Moore <[email protected]> Cc: James Morris <[email protected]> Cc: "Serge E. Hallyn" <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 5a9e347 commit 0b7b870

File tree

3 files changed

+25
-11
lines changed

3 files changed

+25
-11
lines changed

include/linux/string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
177177
extern const char *kstrdup_const(const char *s, gfp_t gfp);
178178
extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
179179
extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
180+
extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
180181
extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
181182

182183
extern char **argv_split(gfp_t gfp, const char *str, int *argcp);

mm/util.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ EXPORT_SYMBOL(kstrndup);
120120
* @len: memory region length
121121
* @gfp: GFP mask to use
122122
*
123-
* Return: newly allocated copy of @src or %NULL in case of error
123+
* Return: newly allocated copy of @src or %NULL in case of error,
124+
* result is physically contiguous. Use kfree() to free.
124125
*/
125126
void *kmemdup(const void *src, size_t len, gfp_t gfp)
126127
{
@@ -133,6 +134,27 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
133134
}
134135
EXPORT_SYMBOL(kmemdup);
135136

137+
/**
138+
* kvmemdup - duplicate region of memory
139+
*
140+
* @src: memory region to duplicate
141+
* @len: memory region length
142+
* @gfp: GFP mask to use
143+
*
144+
* Return: newly allocated copy of @src or %NULL in case of error,
145+
* result may be not physically contiguous. Use kvfree() to free.
146+
*/
147+
void *kvmemdup(const void *src, size_t len, gfp_t gfp)
148+
{
149+
void *p;
150+
151+
p = kvmalloc(len, gfp);
152+
if (p)
153+
memcpy(p, src, len);
154+
return p;
155+
}
156+
EXPORT_SYMBOL(kvmemdup);
157+
136158
/**
137159
* kmemdup_nul - Create a NUL-terminated string from unterminated data
138160
* @s: The data to stringify

security/apparmor/policy_unpack.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,6 @@ VISIBLE_IF_KUNIT bool aa_inbounds(struct aa_ext *e, size_t size)
161161
}
162162
EXPORT_SYMBOL_IF_KUNIT(aa_inbounds);
163163

164-
static void *kvmemdup(const void *src, size_t len)
165-
{
166-
void *p = kvmalloc(len, GFP_KERNEL);
167-
168-
if (p)
169-
memcpy(p, src, len);
170-
return p;
171-
}
172-
173164
/**
174165
* aa_unpack_u16_chunk - test and do bounds checking for a u16 size based chunk
175166
* @e: serialized data read head (NOT NULL)
@@ -1027,7 +1018,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
10271018

10281019
data->key = key;
10291020
data->size = aa_unpack_blob(e, &data->data, NULL);
1030-
data->data = kvmemdup(data->data, data->size);
1021+
data->data = kvmemdup(data->data, data->size, GFP_KERNEL);
10311022
if (data->size && !data->data) {
10321023
kfree_sensitive(data->key);
10331024
kfree_sensitive(data);

0 commit comments

Comments
 (0)