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

Commit 77e5bdf9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull uaccess fixes from Al Viro:
 "Fixes for broken uaccess primitives - mostly lack of proper zeroing
  in copy_from_user()/get_user()/__get_user(), but for several
  architectures there's more (broken clear_user() on frv and
  strncpy_from_user() on hexagon)"

* 'uaccess-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (28 commits)
  avr32: fix copy_from_user()
  microblaze: fix __get_user()
  microblaze: fix copy_from_user()
  m32r: fix __get_user()
  blackfin: fix copy_from_user()
  sparc32: fix copy_from_user()
  sh: fix copy_from_user()
  sh64: failing __get_user() should zero
  score: fix copy_from_user() and friends
  score: fix __get_user/get_user
  s390: get_user() should zero on failure
  ppc32: fix copy_from_user()
  parisc: fix copy_from_user()
  openrisc: fix copy_from_user()
  nios2: fix __get_user()
  nios2: copy_from_user() should zero the tail of destination
  mn10300: copy_from_user() should zero on access_ok() failure...
  mn10300: failing __get_user() and get_user() should zero
  mips: copy_from_user() must zero the destination on access_ok() failure
  ARC: uaccess: get_user to zero out dest in cause of fault
  ...
parents b8f26e88 8630c322
Loading
Loading
Loading
Loading
+8 −11
Original line number Diff line number Diff line
@@ -371,14 +371,6 @@ __copy_tofrom_user_nocheck(void *to, const void *from, long len)
	return __cu_len;
}

extern inline long
__copy_tofrom_user(void *to, const void *from, long len, const void __user *validate)
{
	if (__access_ok((unsigned long)validate, len, get_fs()))
		len = __copy_tofrom_user_nocheck(to, from, len);
	return len;
}

#define __copy_to_user(to, from, n)					\
({									\
	__chk_user_ptr(to);						\
@@ -393,17 +385,22 @@ __copy_tofrom_user(void *to, const void *from, long len, const void __user *vali
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user


extern inline long
copy_to_user(void __user *to, const void *from, long n)
{
	return __copy_tofrom_user((__force void *)to, from, n, to);
	if (likely(__access_ok((unsigned long)to, n, get_fs())))
		n = __copy_tofrom_user_nocheck((__force void *)to, from, n);
	return n;
}

extern inline long
copy_from_user(void *to, const void __user *from, long n)
{
	return __copy_tofrom_user(to, (__force void *)from, n, from);
	if (likely(__access_ok((unsigned long)from, n, get_fs())))
		n = __copy_tofrom_user_nocheck(to, (__force void *)from, n);
	else
		memset(to, 0, n);
	return n;
}

extern void __do_clear_user(void);
+9 −2
Original line number Diff line number Diff line
@@ -83,7 +83,10 @@
	"2:	;nop\n"				\
	"	.section .fixup, \"ax\"\n"	\
	"	.align 4\n"			\
	"3:	mov %0, %3\n"			\
	"3:	# return -EFAULT\n"		\
	"	mov %0, %3\n"			\
	"	# zero out dst ptr\n"		\
	"	mov %1,  0\n"			\
	"	j   2b\n"			\
	"	.previous\n"			\
	"	.section __ex_table, \"a\"\n"	\
@@ -101,7 +104,11 @@
	"2:	;nop\n"				\
	"	.section .fixup, \"ax\"\n"	\
	"	.align 4\n"			\
	"3:	mov %0, %3\n"			\
	"3:	# return -EFAULT\n"		\
	"	mov %0, %3\n"			\
	"	# zero out dst ptr\n"		\
	"	mov %1,  0\n"			\
	"	mov %R1, 0\n"			\
	"	j   2b\n"			\
	"	.previous\n"			\
	"	.section __ex_table, \"a\"\n"	\
+10 −1
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ extern __kernel_size_t __copy_user(void *to, const void *from,

extern __kernel_size_t copy_to_user(void __user *to, const void *from,
				    __kernel_size_t n);
extern __kernel_size_t copy_from_user(void *to, const void __user *from,
extern __kernel_size_t ___copy_from_user(void *to, const void __user *from,
				      __kernel_size_t n);

static inline __kernel_size_t __copy_to_user(void __user *to, const void *from,
@@ -88,6 +88,15 @@ static inline __kernel_size_t __copy_from_user(void *to,
{
	return __copy_user(to, (const void __force *)from, n);
}
static inline __kernel_size_t copy_from_user(void *to,
					       const void __user *from,
					       __kernel_size_t n)
{
	size_t res = ___copy_from_user(to, from, n);
	if (unlikely(res))
		memset(to + (n - res), 0, res);
	return res;
}

#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ EXPORT_SYMBOL(copy_page);
/*
 * Userspace access stuff.
 */
EXPORT_SYMBOL(copy_from_user);
EXPORT_SYMBOL(___copy_from_user);
EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(__copy_user);
EXPORT_SYMBOL(strncpy_from_user);
+2 −2
Original line number Diff line number Diff line
@@ -25,11 +25,11 @@
	.align	1
	.global	copy_from_user
	.type	copy_from_user, @function
copy_from_user:
___copy_from_user:
	branch_if_kernel r8, __copy_user
	ret_if_privileged r8, r11, r10, r10
	rjmp	__copy_user
	.size	copy_from_user, . - copy_from_user
	.size	___copy_from_user, . - ___copy_from_user

	.global	copy_to_user
	.type	copy_to_user, @function
Loading