|
|
@@ -150,7 +150,8 @@ EXPORT_SYMBOL(kmemdup_nul);
|
|
|
* @src: source address in user space
|
|
|
* @len: number of bytes to copy
|
|
|
*
|
|
|
- * Returns an ERR_PTR() on failure.
|
|
|
+ * Returns an ERR_PTR() on failure. Result is physically
|
|
|
+ * contiguous, to be freed by kfree().
|
|
|
*/
|
|
|
void *memdup_user(const void __user *src, size_t len)
|
|
|
{
|
|
|
@@ -169,6 +170,32 @@ void *memdup_user(const void __user *src, size_t len)
|
|
|
}
|
|
|
EXPORT_SYMBOL(memdup_user);
|
|
|
|
|
|
+/**
|
|
|
+ * vmemdup_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. Result may be not
|
|
|
+ * physically contiguous. Use kvfree() to free.
|
|
|
+ */
|
|
|
+void *vmemdup_user(const void __user *src, size_t len)
|
|
|
+{
|
|
|
+ void *p;
|
|
|
+
|
|
|
+ p = kvmalloc(len, GFP_USER);
|
|
|
+ if (!p)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+
|
|
|
+ if (copy_from_user(p, src, len)) {
|
|
|
+ kvfree(p);
|
|
|
+ return ERR_PTR(-EFAULT);
|
|
|
+ }
|
|
|
+
|
|
|
+ return p;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(vmemdup_user);
|
|
|
+
|
|
|
/*
|
|
|
* strndup_user - duplicate an existing string from user space
|
|
|
* @s: The string to duplicate
|