diff options
Diffstat (limited to 'mm/util.c')
-rw-r--r-- | mm/util.c | 36 |
1 files changed, 29 insertions, 7 deletions
@@ -150,18 +150,14 @@ EXPORT_SYMBOL(kmemdup_nul); | |||
150 | * @src: source address in user space | 150 | * @src: source address in user space |
151 | * @len: number of bytes to copy | 151 | * @len: number of bytes to copy |
152 | * | 152 | * |
153 | * Returns an ERR_PTR() on failure. | 153 | * Returns an ERR_PTR() on failure. Result is physically |
154 | * contiguous, to be freed by kfree(). | ||
154 | */ | 155 | */ |
155 | void *memdup_user(const void __user *src, size_t len) | 156 | void *memdup_user(const void __user *src, size_t len) |
156 | { | 157 | { |
157 | void *p; | 158 | void *p; |
158 | 159 | ||
159 | /* | 160 | p = kmalloc_track_caller(len, GFP_USER); |
160 | * Always use GFP_KERNEL, since copy_from_user() can sleep and | ||
161 | * cause pagefault, which makes it pointless to use GFP_NOFS | ||
162 | * or GFP_ATOMIC. | ||
163 | */ | ||
164 | p = kmalloc_track_caller(len, GFP_KERNEL); | ||
165 | if (!p) | 161 | if (!p) |
166 | return ERR_PTR(-ENOMEM); | 162 | return ERR_PTR(-ENOMEM); |
167 | 163 | ||
@@ -174,6 +170,32 @@ void *memdup_user(const void __user *src, size_t len) | |||
174 | } | 170 | } |
175 | EXPORT_SYMBOL(memdup_user); | 171 | EXPORT_SYMBOL(memdup_user); |
176 | 172 | ||
173 | /** | ||
174 | * vmemdup_user - duplicate memory region from user space | ||
175 | * | ||
176 | * @src: source address in user space | ||
177 | * @len: number of bytes to copy | ||
178 | * | ||
179 | * Returns an ERR_PTR() on failure. Result may be not | ||
180 | * physically contiguous. Use kvfree() to free. | ||
181 | */ | ||
182 | void *vmemdup_user(const void __user *src, size_t len) | ||
183 | { | ||
184 | void *p; | ||
185 | |||
186 | p = kvmalloc(len, GFP_USER); | ||
187 | if (!p) | ||
188 | return ERR_PTR(-ENOMEM); | ||
189 | |||
190 | if (copy_from_user(p, src, len)) { | ||
191 | kvfree(p); | ||
192 | return ERR_PTR(-EFAULT); | ||
193 | } | ||
194 | |||
195 | return p; | ||
196 | } | ||
197 | EXPORT_SYMBOL(vmemdup_user); | ||
198 | |||
177 | /* | 199 | /* |
178 | * strndup_user - duplicate an existing string from user space | 200 | * strndup_user - duplicate an existing string from user space |
179 | * @s: The string to duplicate | 201 | * @s: The string to duplicate |