Skip to content

Commit

Permalink
memdup_user(): introduce
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Americo Wang <[email protected]>
Cc: Alexey Dobriyan <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Li Zefan authored and torvalds committed Apr 1, 2009
1 parent e2f17d9 commit 610a77e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/stddef.h> /* for NULL */

extern char *strndup_user(const char __user *, long);
extern void *memdup_user(const void __user *, size_t);

/*
* Include machine specific inline routines
Expand Down
30 changes: 30 additions & 0 deletions mm/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 610a77e

Please sign in to comment.