Commit f94c128e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull metag updates from James Hogan:
 "These patches primarily make some usercopy improvements (following on
  from the recent usercopy fixes):

   - reformat and simplify rapf copy loops

   - add 64-bit get_user support

  And fix a couple more uaccess issues, partily pointed out by Al:

   - fix access_ok() serious shortcomings

   - fix strncpy_from_user() address validation

  Also included is a trivial removal of a redundant increment"

* tag 'metag-for-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag:
  metag/mm: Drop pointless increment
  metag/uaccess: Check access_ok in strncpy_from_user
  metag/uaccess: Fix access_ok()
  metag/usercopy: Add 64-bit get_user support
  metag/usercopy: Simplify rapf loop fixup corner case
  metag/usercopy: Reformat rapf loop inline asm
parents c44b5943 e3cd7f01
Loading
Loading
Loading
Loading
+38 −20
Original line number Diff line number Diff line
@@ -24,24 +24,32 @@

#define segment_eq(a, b)	((a).seg == (b).seg)

#define __kernel_ok (uaccess_kernel())
static inline int __access_ok(unsigned long addr, unsigned long size)
{
	/*
	 * Allow access to the user mapped memory area, but not the system area
	 * before it. The check extends to the top of the address space when
	 * kernel access is allowed (there's no real reason to user copy to the
	 * system area in any case).
	 */
	if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg &&
		   size <= get_fs().seg - addr))
		return true;
	/*
	 * Explicitly allow NULL pointers here. Parts of the kernel such
	 * as readv/writev use access_ok to validate pointers, but want
	 * to allow NULL pointers for various reasons. NULL pointers are
	 * safe to allow through because the first page is not mappable on
	 * Meta.
 *
 * We also wish to avoid letting user code access the system area
 * and the kernel half of the address space.
	 */
#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \
				((addr) > PAGE_OFFSET &&		\
				 (addr) < LINCORE_BASE))

static inline int __access_ok(unsigned long addr, unsigned long size)
{
	return __kernel_ok || !__user_bad(addr, size);
	if (!addr)
		return true;
	/* Allow access to core code memory area... */
	if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT &&
	    size <= LINCORE_CODE_LIMIT + 1 - addr)
		return true;
	/* ... but no other areas. */
	return false;
}

#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),	\
@@ -113,7 +121,8 @@ extern long __get_user_bad(void);

#define __get_user_nocheck(x, ptr, size)			\
({                                                              \
	long __gu_err, __gu_val;                                \
	long __gu_err;						\
	long long __gu_val;					\
	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
	(x) = (__force __typeof__(*(ptr)))__gu_val;             \
	__gu_err;                                               \
@@ -121,7 +130,8 @@ extern long __get_user_bad(void);

#define __get_user_check(x, ptr, size)					\
({                                                                      \
	long __gu_err = -EFAULT, __gu_val = 0;                          \
	long __gu_err = -EFAULT;					\
	long long __gu_val = 0;						\
	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
	if (access_ok(VERIFY_READ, __gu_addr, size))			\
		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
@@ -132,6 +142,7 @@ extern long __get_user_bad(void);
extern unsigned char __get_user_asm_b(const void __user *addr, long *err);
extern unsigned short __get_user_asm_w(const void __user *addr, long *err);
extern unsigned int __get_user_asm_d(const void __user *addr, long *err);
extern unsigned long long __get_user_asm_l(const void __user *addr, long *err);

#define __get_user_size(x, ptr, size, retval)			\
do {                                                            \
@@ -143,6 +154,8 @@ do { \
		x = __get_user_asm_w(ptr, &retval); break;	\
	case 4:							\
		x = __get_user_asm_d(ptr, &retval); break;	\
	case 8:							\
		x = __get_user_asm_l(ptr, &retval); break;	\
	default:						\
		(x) = __get_user_bad();				\
	}                                                       \
@@ -161,8 +174,13 @@ do { \
extern long __must_check __strncpy_from_user(char *dst, const char __user *src,
					     long count);

#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count)

static inline long
strncpy_from_user(char *dst, const char __user *src, long count)
{
	if (!access_ok(VERIFY_READ, src, 1))
		return -EFAULT;
	return __strncpy_from_user(dst, src, count);
}
/*
 * Return the size of a string (including the ending 0)
 *
+105 −131
Original line number Diff line number Diff line
@@ -255,39 +255,24 @@
		"	MOV	RAPF, %1\n"				\
		"$Lloop"id":\n"						\
		"	ADD	RAPF, %1, #64\n"			\
		"21:\n"							\
		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"22:\n"							\
		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"23:\n"							\
		"SUB	%3, %3, #32\n"					\
		"24:\n"							\
		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"25:\n"							\
		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"26:\n"							\
		"SUB	%3, %3, #32\n"					\
		"21:	MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"22:	MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"23:	SUB	%3, %3, #32\n"				\
		"24:	MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"25:	MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"26:	SUB	%3, %3, #32\n"				\
		"	DCACHE	[%1+#-64], D0Ar6\n"			\
		"	BR	$Lloop"id"\n"				\
									\
		"	MOV	RAPF, %1\n"				\
		"27:\n"							\
		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"28:\n"							\
		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"29:\n"							\
		"27:	MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"28:	MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"29:	SUB	%3, %3, #32\n"				\
		"30:	MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"31:	MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"32:	SETL	[%0+#-8], D0.7, D1.7\n"			\
		"	SUB	%3, %3, #32\n"				\
		"30:\n"							\
		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"31:\n"							\
		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"32:\n"							\
		"SUB	%0, %0, #8\n"					\
		"33:\n"							\
		"SETL	[%0++], D0.7, D1.7\n"				\
		"SUB	%3, %3, #32\n"					\
		"1:"							\
		"DCACHE	[%1+#-64], D0Ar6\n"				\
		"1:	DCACHE	[%1+#-64], D0Ar6\n"			\
		"	GETL	D0Ar6, D1Ar5, [A0StP+#-40]\n"		\
		"	GETL	D0FrT, D1RtP, [A0StP+#-32]\n"		\
		"	GETL	D0.5, D1.5, [A0StP+#-24]\n"		\
@@ -295,10 +280,7 @@
		"	GETL	D0.7, D1.7, [A0StP+#-8]\n"		\
		"	SUB	A0StP, A0StP, #40\n"			\
		"	.section .fixup,\"ax\"\n"			\
		"4:\n"							\
		"	ADD	%0, %0, #8\n"				\
		"3:\n"							\
		"	MOV	D0Ar2, TXSTATUS\n"			\
		"3:	MOV	D0Ar2, TXSTATUS\n"			\
		"	MOV	D1Ar1, TXSTATUS\n"			\
		"	AND	D1Ar1, D1Ar1, #0xFFFFF8FF\n"		\
		"	MOV	TXSTATUS, D1Ar1\n"			\
@@ -319,7 +301,6 @@
		"	.long 30b,3b\n"					\
		"	.long 31b,3b\n"					\
		"	.long 32b,3b\n"					\
		"	.long 33b,4b\n"					\
		"	.previous\n"					\
		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
@@ -406,63 +387,36 @@
		"	MOV	RAPF, %1\n"				\
		"$Lloop"id":\n"						\
		"	ADD	RAPF, %1, #64\n"			\
		"21:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"22:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"23:\n"							\
		"SUB	%3, %3, #16\n"					\
		"24:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"25:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"26:\n"							\
		"SUB	%3, %3, #16\n"					\
		"27:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"28:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"29:\n"							\
		"SUB	%3, %3, #16\n"					\
		"30:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"31:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"32:\n"							\
		"SUB	%3, %3, #16\n"					\
		"21:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"22:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"23:	SUB	%3, %3, #16\n"				\
		"24:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"25:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"26:	SUB	%3, %3, #16\n"				\
		"27:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"28:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"29:	SUB	%3, %3, #16\n"				\
		"30:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"31:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"32:	SUB	%3, %3, #16\n"				\
		"	DCACHE	[%1+#-64], D0Ar6\n"			\
		"	BR	$Lloop"id"\n"				\
									\
		"	MOV	RAPF, %1\n"				\
		"33:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"34:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"35:\n"							\
		"33:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"34:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"35:	SUB	%3, %3, #16\n"				\
		"36:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"37:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"38:	SUB	%3, %3, #16\n"				\
		"39:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"40:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"41:	SUB	%3, %3, #16\n"				\
		"42:	MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"	\
		"43:	MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"	\
		"44:	SETD	[%0+#-4], D0.7\n"			\
		"	SUB	%3, %3, #16\n"				\
		"36:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"37:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"38:\n"							\
		"SUB	%3, %3, #16\n"					\
		"39:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"40:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"41:\n"							\
		"SUB	%3, %3, #16\n"					\
		"42:\n"							\
		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
		"43:\n"							\
		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
		"44:\n"							\
		"SUB	%0, %0, #4\n"					\
		"45:\n"							\
		"SETD	[%0++], D0.7\n"					\
		"SUB	%3, %3, #16\n"					\
		"1:"							\
		"DCACHE	[%1+#-64], D0Ar6\n"				\
		"1:	DCACHE	[%1+#-64], D0Ar6\n"			\
		"	GETL	D0Ar6, D1Ar5, [A0StP+#-40]\n"		\
		"	GETL	D0FrT, D1RtP, [A0StP+#-32]\n"		\
		"	GETL	D0.5, D1.5, [A0StP+#-24]\n"		\
@@ -470,10 +424,7 @@
		"	GETL	D0.7, D1.7, [A0StP+#-8]\n"		\
		"	SUB A0StP, A0StP, #40\n"			\
		"	.section .fixup,\"ax\"\n"			\
		"4:\n"							\
		"	ADD		%0, %0, #4\n"			\
		"3:\n"							\
		"	MOV	D0Ar2, TXSTATUS\n"			\
		"3:	MOV	D0Ar2, TXSTATUS\n"			\
		"	MOV	D1Ar1, TXSTATUS\n"			\
		"	AND	D1Ar1, D1Ar1, #0xFFFFF8FF\n"		\
		"	MOV	TXSTATUS, D1Ar1\n"			\
@@ -506,7 +457,6 @@
		"	.long 42b,3b\n"					\
		"	.long 43b,3b\n"					\
		"	.long 44b,3b\n"					\
		"	.long 45b,4b\n"					\
		"	.previous\n"					\
		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
@@ -1094,6 +1044,30 @@ unsigned int __get_user_asm_d(const void __user *addr, long *err)
}
EXPORT_SYMBOL(__get_user_asm_d);

unsigned long long __get_user_asm_l(const void __user *addr, long *err)
{
	register unsigned long long x asm ("D0Re0") = 0;
	asm volatile (
		"	GETL %0,%t0,[%2]\n"
		"1:\n"
		"	GETL %0,%t0,[%2]\n"
		"2:\n"
		"	.section .fixup,\"ax\"\n"
		"3:	MOV     D0FrT,%3\n"
		"	SETD    [%1],D0FrT\n"
		"	MOVT    D0FrT,#HI(2b)\n"
		"	JUMP    D0FrT,#LO(2b)\n"
		"	.previous\n"
		"	.section __ex_table,\"a\"\n"
		"	.long 1b,3b\n"
		"	.previous\n"
		: "=r" (x)
		: "r" (err), "r" (addr), "P" (-EFAULT)
		: "D0FrT");
	return x;
}
EXPORT_SYMBOL(__get_user_asm_l);

long __put_user_asm_b(unsigned int x, void __user *addr)
{
	register unsigned int err asm ("D0Re0") = 0;
+0 −1
Original line number Diff line number Diff line
@@ -152,6 +152,5 @@ void __init mmu_init(unsigned long mem_end)

		p_swapper_pg_dir++;
		addr += PGDIR_SIZE;
		entry++;
	}
}