Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb47e029 authored by Al Viro's avatar Al Viro
Browse files

cris: buggered copy_from_user/copy_to_user/clear_user



* copy_from_user() on access_ok() failure ought to zero the destination
* none of those primitives should skip the access_ok() check in case of
small constant size.

Cc: stable@vger.kernel.org
Acked-by: default avatarJesper Nilsson <jesper.nilsson@axis.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 9ad18b75
Loading
Loading
Loading
Loading
+32 −39
Original line number Original line Diff line number Diff line
@@ -194,30 +194,6 @@ extern unsigned long __copy_user(void __user *to, const void *from, unsigned lon
extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n);
extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n);
extern unsigned long __do_clear_user(void __user *to, unsigned long n);
extern unsigned long __do_clear_user(void __user *to, unsigned long n);


static inline unsigned long
__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{
	if (access_ok(VERIFY_WRITE, to, n))
		return __copy_user(to, from, n);
	return n;
}

static inline unsigned long
__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{
	if (access_ok(VERIFY_READ, from, n))
		return __copy_user_zeroing(to, from, n);
	return n;
}

static inline unsigned long
__generic_clear_user(void __user *to, unsigned long n)
{
	if (access_ok(VERIFY_WRITE, to, n))
		return __do_clear_user(to, n);
	return n;
}

static inline long
static inline long
__strncpy_from_user(char *dst, const char __user *src, long count)
__strncpy_from_user(char *dst, const char __user *src, long count)
{
{
@@ -282,7 +258,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
	else if (n == 24)
	else if (n == 24)
		__asm_copy_from_user_24(to, from, ret);
		__asm_copy_from_user_24(to, from, ret);
	else
	else
		ret = __generic_copy_from_user(to, from, n);
		ret = __copy_user_zeroing(to, from, n);


	return ret;
	return ret;
}
}
@@ -333,7 +309,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
	else if (n == 24)
	else if (n == 24)
		__asm_copy_to_user_24(to, from, ret);
		__asm_copy_to_user_24(to, from, ret);
	else
	else
		ret = __generic_copy_to_user(to, from, n);
		ret = __copy_user(to, from, n);


	return ret;
	return ret;
}
}
@@ -366,26 +342,43 @@ __constant_clear_user(void __user *to, unsigned long n)
	else if (n == 24)
	else if (n == 24)
		__asm_clear_24(to, ret);
		__asm_clear_24(to, ret);
	else
	else
		ret = __generic_clear_user(to, n);
		ret = __do_clear_user(to, n);


	return ret;
	return ret;
}
}




#define clear_user(to, n)				\
static inline size_t clear_user(void __user *to, size_t n)
	(__builtin_constant_p(n) ?			\
{
	 __constant_clear_user(to, n) :			\
	if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
	 __generic_clear_user(to, n))
		return n;
	if (__builtin_constant_p(n))
		return __constant_clear_user(to, n);
	else
		return __do_clear_user(to, n);
}


#define copy_from_user(to, from, n)			\
static inline size_t copy_from_user(void *to, const void __user *from, size_t n)
	(__builtin_constant_p(n) ?			\
{
	 __constant_copy_from_user(to, from, n) :	\
	if (unlikely(!access_ok(VERIFY_READ, from, n))) {
	 __generic_copy_from_user(to, from, n))
		memset(to, 0, n);
		return n;
	}
	if (__builtin_constant_p(n))
		return __constant_copy_from_user(to, from, n);
	else
		return __copy_user_zeroing(to, from, n);
}


#define copy_to_user(to, from, n)			\
static inline size_t copy_to_user(void __user *to, const void *from, size_t n)
	(__builtin_constant_p(n) ?			\
{
	 __constant_copy_to_user(to, from, n) :		\
	if (unlikely(!access_ok(VERIFY_WRITE, to, n)))
	 __generic_copy_to_user(to, from, n))
		return n;
	if (__builtin_constant_p(n))
		return __constant_copy_to_user(to, from, n);
	else
		return __copy_user(to, from, n);
}


/* We let the __ versions of copy_from/to_user inline, because they're often
/* We let the __ versions of copy_from/to_user inline, because they're often
 * used in fast paths and have only a small space overhead.
 * used in fast paths and have only a small space overhead.