diff options
Diffstat (limited to 'mm/util.c')
| -rw-r--r-- | mm/util.c | 30 |
1 files changed, 30 insertions, 0 deletions
| @@ -70,6 +70,36 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) | |||
| 70 | EXPORT_SYMBOL(kmemdup); | 70 | EXPORT_SYMBOL(kmemdup); |
| 71 | 71 | ||
| 72 | /** | 72 | /** |
| 73 | * memdup_user - duplicate memory region from user space | ||
| 74 | * | ||
| 75 | * @src: source address in user space | ||
| 76 | * @len: number of bytes to copy | ||
| 77 | * | ||
| 78 | * Returns an ERR_PTR() on failure. | ||
| 79 | */ | ||
| 80 | void *memdup_user(const void __user *src, size_t len) | ||
| 81 | { | ||
| 82 | void *p; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Always use GFP_KERNEL, since copy_from_user() can sleep and | ||
| 86 | * cause pagefault, which makes it pointless to use GFP_NOFS | ||
| 87 | * or GFP_ATOMIC. | ||
| 88 | */ | ||
| 89 | p = kmalloc_track_caller(len, GFP_KERNEL); | ||
| 90 | if (!p) | ||
| 91 | return ERR_PTR(-ENOMEM); | ||
| 92 | |||
| 93 | if (copy_from_user(p, src, len)) { | ||
| 94 | kfree(p); | ||
| 95 | return ERR_PTR(-EFAULT); | ||
| 96 | } | ||
| 97 | |||
| 98 | return p; | ||
| 99 | } | ||
| 100 | EXPORT_SYMBOL(memdup_user); | ||
| 101 | |||
| 102 | /** | ||
| 73 | * __krealloc - like krealloc() but don't free @p. | 103 | * __krealloc - like krealloc() but don't free @p. |
| 74 | * @p: object to reallocate memory for. | 104 | * @p: object to reallocate memory for. |
| 75 | * @new_size: how many bytes of memory are required. | 105 | * @new_size: how many bytes of memory are required. |
