[PATCH] kmemdup: introduce
One of idiomatic ways to duplicate a region of memory is dst = kmalloc(len, GFP_KERNEL); if (!dst) return -ENOMEM; memcpy(dst, src, len); which is neat code except a programmer needs to write size twice. Which sometimes leads to mistakes. If len passed to kmalloc is smaller that len passed to memcpy, it's straight overwrite-beyond-end. If len passed to memcpy is smaller than len passed to kmalloc, it's either a) legit behaviour ;-), or b) cloned buffer will contain garbage in second half. Slight trolling of commit lists shows several duplications bugs done exactly because of diverged lenghts: Linux: [CRYPTO]: Fix memcpy/memset args. [PATCH] memcpy/memset fixes OpenBSD: kerberosV/src/lib/asn1: der_copy.c:1.4 If programmer is given only one place to play with lengths, I believe, such mistakes could be avoided. With kmemdup, the snippet above will be rewritten as: dst = kmemdup(src, len, GFP_KERNEL); if (!dst) return -ENOMEM; This also leads to smaller code (kzalloc effect). Quick grep shows 200+ places where kmemdup() can be used. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
9442e691e4
Коммит
1a2f67b459
|
@ -99,6 +99,7 @@ extern void * memchr(const void *,int,__kernel_size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char *kstrdup(const char *s, gfp_t gfp);
|
extern char *kstrdup(const char *s, gfp_t gfp);
|
||||||
|
extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
18
mm/util.c
18
mm/util.c
|
@ -40,6 +40,24 @@ char *kstrdup(const char *s, gfp_t gfp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kstrdup);
|
EXPORT_SYMBOL(kstrdup);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kmemdup - duplicate region of memory
|
||||||
|
*
|
||||||
|
* @src: memory region to duplicate
|
||||||
|
* @len: memory region length
|
||||||
|
* @gfp: GFP mask to use
|
||||||
|
*/
|
||||||
|
void *kmemdup(const void *src, size_t len, gfp_t gfp)
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
p = ____kmalloc(len, gfp);
|
||||||
|
if (p)
|
||||||
|
memcpy(p, src, len);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(kmemdup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* strndup_user - duplicate an existing string from user space
|
* strndup_user - duplicate an existing string from user space
|
||||||
*
|
*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче