Commit 8ac6f5d7 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Russell King (Oracle)
Browse files

ARM: 9113/1: uaccess: remove set_fs() implementation



There are no remaining callers of set_fs(), so just remove it
along with all associated code that operates on
thread_info->addr_limit.

There are still further optimizations that can be done:

- In get_user(), the address check could be moved entirely
  into the out of line code, rather than passing a constant
  as an argument,

- I assume the DACR handling can be simplified as we now
  only change it during user access when CONFIG_CPU_SW_DOMAIN_PAN
  is set, but not during set_fs().

Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
parent 2df4c9a7
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -126,7 +126,6 @@ config ARM
	select PCI_SYSCALL if PCI
	select PERF_USE_VMALLOC
	select RTC_LIB
	select SET_FS
	select SYS_SUPPORTS_APM_EMULATION
	# Above selects are sorted alphabetically; please add new ones
	# according to that.  Thanks.
+0 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ struct pt_regs {
struct svc_pt_regs {
	struct pt_regs regs;
	u32 dacr;
	u32 addr_limit;
};

#define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)
+0 −4
Original line number Diff line number Diff line
@@ -31,8 +31,6 @@ struct task_struct;

#include <asm/types.h>

typedef unsigned long mm_segment_t;

struct cpu_context_save {
	__u32	r4;
	__u32	r5;
@@ -54,7 +52,6 @@ struct cpu_context_save {
struct thread_info {
	unsigned long		flags;		/* low level flags */
	int			preempt_count;	/* 0 => preemptable, <0 => bug */
	mm_segment_t		addr_limit;	/* address limit */
	struct task_struct	*task;		/* main task structure */
	__u32			cpu;		/* cpu */
	__u32			cpu_domain;	/* cpu domain */
@@ -80,7 +77,6 @@ struct thread_info {
	.task		= &tsk,						\
	.flags		= 0,						\
	.preempt_count	= INIT_PREEMPT_COUNT,				\
	.addr_limit	= KERNEL_DS,					\
}

/*
+0 −6
Original line number Diff line number Diff line
@@ -84,12 +84,8 @@
	 * if \disable is set.
	 */
	.macro	uaccess_entry, tsk, tmp0, tmp1, tmp2, disable
	ldr	\tmp1, [\tsk, #TI_ADDR_LIMIT]
	ldr	\tmp2, =TASK_SIZE
	str	\tmp2, [\tsk, #TI_ADDR_LIMIT]
 DACR(	mrc	p15, 0, \tmp0, c3, c0, 0)
 DACR(	str	\tmp0, [sp, #SVC_DACR])
	str	\tmp1, [sp, #SVC_ADDR_LIMIT]
	.if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN)
	/* kernel=client, user=no access */
	mov	\tmp2, #DACR_UACCESS_DISABLE
@@ -106,9 +102,7 @@

	/* Restore the user access state previously saved by uaccess_entry */
	.macro	uaccess_exit, tsk, tmp0, tmp1
	ldr	\tmp1, [sp, #SVC_ADDR_LIMIT]
 DACR(	ldr	\tmp0, [sp, #SVC_DACR])
	str	\tmp1, [\tsk, #TI_ADDR_LIMIT]
 DACR(	mcr	p15, 0, \tmp0, c3, c0, 0)
	.endm

+4 −42
Original line number Diff line number Diff line
@@ -52,32 +52,8 @@ static __always_inline void uaccess_restore(unsigned int flags)
extern int __get_user_bad(void);
extern int __put_user_bad(void);

/*
 * Note that this is actually 0x1,0000,0000
 */
#define KERNEL_DS	0x00000000

#ifdef CONFIG_MMU

#define USER_DS		TASK_SIZE
#define get_fs()	(current_thread_info()->addr_limit)

static inline void set_fs(mm_segment_t fs)
{
	current_thread_info()->addr_limit = fs;

	/*
	 * Prevent a mispredicted conditional call to set_fs from forwarding
	 * the wrong address limit to access_ok under speculation.
	 */
	dsb(nsh);
	isb();

	modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER);
}

#define uaccess_kernel()	(get_fs() == KERNEL_DS)

/*
 * We use 33-bit arithmetic here.  Success returns zero, failure returns
 * addr_limit.  We take advantage that addr_limit will be zero for KERNEL_DS,
@@ -89,7 +65,7 @@ static inline void set_fs(mm_segment_t fs)
	__asm__(".syntax unified\n" \
		"adds %1, %2, %3; sbcscc %1, %1, %0; movcc %0, #0" \
		: "=&r" (flag), "=&r" (roksum) \
		: "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \
		: "r" (addr), "Ir" (size), "0" (TASK_SIZE) \
		: "cc"); \
	flag; })

@@ -120,7 +96,7 @@ static inline void __user *__uaccess_mask_range_ptr(const void __user *ptr,
	"	subshs	%1, %1, %2\n"
	"	movlo	%0, #0\n"
	: "+r" (safe_ptr), "=&r" (tmp)
	: "r" (size), "r" (current_thread_info()->addr_limit)
	: "r" (size), "r" (TASK_SIZE)
	: "cc");

	csdb();
@@ -194,7 +170,7 @@ extern int __get_user_64t_4(void *);

#define __get_user_check(x, p)						\
	({								\
		unsigned long __limit = current_thread_info()->addr_limit - 1; \
		unsigned long __limit = TASK_SIZE - 1; \
		register typeof(*(p)) __user *__p asm("r0") = (p);	\
		register __inttype(x) __r2 asm("r2");			\
		register unsigned long __l asm("r1") = __limit;		\
@@ -245,7 +221,7 @@ extern int __put_user_8(void *, unsigned long long);

#define __put_user_check(__pu_val, __ptr, __err, __s)			\
	({								\
		unsigned long __limit = current_thread_info()->addr_limit - 1; \
		unsigned long __limit = TASK_SIZE - 1; \
		register typeof(__pu_val) __r2 asm("r2") = __pu_val;	\
		register const void __user *__p asm("r0") = __ptr;	\
		register unsigned long __l asm("r1") = __limit;		\
@@ -262,19 +238,8 @@ extern int __put_user_8(void *, unsigned long long);

#else /* CONFIG_MMU */

/*
 * uClinux has only one addr space, so has simplified address limits.
 */
#define USER_DS			KERNEL_DS

#define uaccess_kernel()	(true)
#define __addr_ok(addr)		((void)(addr), 1)
#define __range_ok(addr, size)	((void)(addr), 0)
#define get_fs()		(KERNEL_DS)

static inline void set_fs(mm_segment_t fs)
{
}

#define get_user(x, p)	__get_user(x, p)
#define __put_user_check __put_user_nocheck
@@ -283,9 +248,6 @@ static inline void set_fs(mm_segment_t fs)

#define access_ok(addr, size)	(__range_ok(addr, size) == 0)

#define user_addr_max() \
	(uaccess_kernel() ? ~0UL : get_fs())

#ifdef CONFIG_CPU_SPECTRE
/*
 * When mitigating Spectre variant 1, it is not worth fixing the non-
Loading