From 050145f45590afa8ef3f39e743d2d5d71af0645c Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Tue, 31 Mar 2009 15:23:16 -0700 Subject: [PATCH] --- yaml --- r: 139154 b: refs/heads/master c: 610a77e04a8d9fe8764dc484e2182fa251ce1cc2 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/string.h | 1 + trunk/mm/util.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 8752f9b10d11..3807964982a3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e2f17d9459aeccf4e013e31cbd741d6b1858eec4 +refs/heads/master: 610a77e04a8d9fe8764dc484e2182fa251ce1cc2 diff --git a/trunk/include/linux/string.h b/trunk/include/linux/string.h index d18fc198aa2f..8852739f36df 100644 --- a/trunk/include/linux/string.h +++ b/trunk/include/linux/string.h @@ -12,6 +12,7 @@ #include /* for NULL */ extern char *strndup_user(const char __user *, long); +extern void *memdup_user(const void __user *, size_t); /* * Include machine specific inline routines diff --git a/trunk/mm/util.c b/trunk/mm/util.c index 37eaccdf3054..7c122e49f769 100644 --- a/trunk/mm/util.c +++ b/trunk/mm/util.c @@ -69,6 +69,36 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) } EXPORT_SYMBOL(kmemdup); +/** + * memdup_user - duplicate memory region from user space + * + * @src: source address in user space + * @len: number of bytes to copy + * + * Returns an ERR_PTR() on failure. + */ +void *memdup_user(const void __user *src, size_t len) +{ + void *p; + + /* + * Always use GFP_KERNEL, since copy_from_user() can sleep and + * cause pagefault, which makes it pointless to use GFP_NOFS + * or GFP_ATOMIC. + */ + p = kmalloc_track_caller(len, GFP_KERNEL); + if (!p) + return ERR_PTR(-ENOMEM); + + if (copy_from_user(p, src, len)) { + kfree(p); + return ERR_PTR(-EFAULT); + } + + return p; +} +EXPORT_SYMBOL(memdup_user); + /** * __krealloc - like krealloc() but don't free @p. * @p: object to reallocate memory for.