Commit 610a77e04a8d9fe8764dc484e2182fa251ce1cc2

Authored by Li Zefan
Committed by Linus Torvalds
1 parent e2f17d9459

memdup_user(): introduce

I notice there are many places doing copy_from_user() which follows
kmalloc():

        dst = kmalloc(len, GFP_KERNEL);
        if (!dst)
                return -ENOMEM;
        if (copy_from_user(dst, src, len)) {
		kfree(dst);
		return -EFAULT
	}

memdup_user() is a wrapper of the above code.  With this new function, we
don't have to write 'len' twice, which can lead to typos/mistakes.  It
also produces smaller code and kernel text.

A quick grep shows 250+ places where memdup_user() *may* be used.  I'll
prepare a patchset to do this conversion.

Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Americo Wang <xiyou.wangcong@gmail.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 31 additions and 0 deletions Side-by-side Diff

include/linux/string.h
... ... @@ -12,6 +12,7 @@
12 12 #include <linux/stddef.h> /* for NULL */
13 13  
14 14 extern char *strndup_user(const char __user *, long);
  15 +extern void *memdup_user(const void __user *, size_t);
15 16  
16 17 /*
17 18 * Include machine specific inline routines
... ... @@ -70,6 +70,36 @@
70 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 103 * __krealloc - like krealloc() but don't free @p.
74 104 * @p: object to reallocate memory for.
75 105 * @new_size: how many bytes of memory are required.