[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:
parent
9442e691e4
commit
1a2f67b459
|
@ -99,6 +99,7 @@ extern void * memchr(const void *,int,__kernel_size_t);
|
|||
#endif
|
||||
|
||||
extern char *kstrdup(const char *s, gfp_t gfp);
|
||||
extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
|
||||
|
||||
#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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue