Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>

authored by

Arnd Bergmann and committed by
Russell King (Oracle)
8ac6f5d7 2df4c9a7

+7 -86
-1
arch/arm/Kconfig
··· 126 126 select PCI_SYSCALL if PCI 127 127 select PERF_USE_VMALLOC 128 128 select RTC_LIB 129 - select SET_FS 130 129 select SYS_SUPPORTS_APM_EMULATION 131 130 # Above selects are sorted alphabetically; please add new ones 132 131 # according to that. Thanks.
-1
arch/arm/include/asm/ptrace.h
··· 19 19 struct svc_pt_regs { 20 20 struct pt_regs regs; 21 21 u32 dacr; 22 - u32 addr_limit; 23 22 }; 24 23 25 24 #define to_svc_pt_regs(r) container_of(r, struct svc_pt_regs, regs)
-4
arch/arm/include/asm/thread_info.h
··· 31 31 32 32 #include <asm/types.h> 33 33 34 - typedef unsigned long mm_segment_t; 35 - 36 34 struct cpu_context_save { 37 35 __u32 r4; 38 36 __u32 r5; ··· 52 54 struct thread_info { 53 55 unsigned long flags; /* low level flags */ 54 56 int preempt_count; /* 0 => preemptable, <0 => bug */ 55 - mm_segment_t addr_limit; /* address limit */ 56 57 struct task_struct *task; /* main task structure */ 57 58 __u32 cpu; /* cpu */ 58 59 __u32 cpu_domain; /* cpu domain */ ··· 77 80 .task = &tsk, \ 78 81 .flags = 0, \ 79 82 .preempt_count = INIT_PREEMPT_COUNT, \ 80 - .addr_limit = KERNEL_DS, \ 81 83 } 82 84 83 85 /*
-6
arch/arm/include/asm/uaccess-asm.h
··· 84 84 * if \disable is set. 85 85 */ 86 86 .macro uaccess_entry, tsk, tmp0, tmp1, tmp2, disable 87 - ldr \tmp1, [\tsk, #TI_ADDR_LIMIT] 88 - ldr \tmp2, =TASK_SIZE 89 - str \tmp2, [\tsk, #TI_ADDR_LIMIT] 90 87 DACR( mrc p15, 0, \tmp0, c3, c0, 0) 91 88 DACR( str \tmp0, [sp, #SVC_DACR]) 92 - str \tmp1, [sp, #SVC_ADDR_LIMIT] 93 89 .if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN) 94 90 /* kernel=client, user=no access */ 95 91 mov \tmp2, #DACR_UACCESS_DISABLE ··· 102 106 103 107 /* Restore the user access state previously saved by uaccess_entry */ 104 108 .macro uaccess_exit, tsk, tmp0, tmp1 105 - ldr \tmp1, [sp, #SVC_ADDR_LIMIT] 106 109 DACR( ldr \tmp0, [sp, #SVC_DACR]) 107 - str \tmp1, [\tsk, #TI_ADDR_LIMIT] 108 110 DACR( mcr p15, 0, \tmp0, c3, c0, 0) 109 111 .endm 110 112
+4 -42
arch/arm/include/asm/uaccess.h
··· 52 52 extern int __get_user_bad(void); 53 53 extern int __put_user_bad(void); 54 54 55 - /* 56 - * Note that this is actually 0x1,0000,0000 57 - */ 58 - #define KERNEL_DS 0x00000000 59 - 60 55 #ifdef CONFIG_MMU 61 - 62 - #define USER_DS TASK_SIZE 63 - #define get_fs() (current_thread_info()->addr_limit) 64 - 65 - static inline void set_fs(mm_segment_t fs) 66 - { 67 - current_thread_info()->addr_limit = fs; 68 - 69 - /* 70 - * Prevent a mispredicted conditional call to set_fs from forwarding 71 - * the wrong address limit to access_ok under speculation. 72 - */ 73 - dsb(nsh); 74 - isb(); 75 - 76 - modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); 77 - } 78 - 79 - #define uaccess_kernel() (get_fs() == KERNEL_DS) 80 56 81 57 /* 82 58 * We use 33-bit arithmetic here. Success returns zero, failure returns ··· 65 89 __asm__(".syntax unified\n" \ 66 90 "adds %1, %2, %3; sbcscc %1, %1, %0; movcc %0, #0" \ 67 91 : "=&r" (flag), "=&r" (roksum) \ 68 - : "r" (addr), "Ir" (size), "0" (current_thread_info()->addr_limit) \ 92 + : "r" (addr), "Ir" (size), "0" (TASK_SIZE) \ 69 93 : "cc"); \ 70 94 flag; }) 71 95 ··· 96 120 " subshs %1, %1, %2\n" 97 121 " movlo %0, #0\n" 98 122 : "+r" (safe_ptr), "=&r" (tmp) 99 - : "r" (size), "r" (current_thread_info()->addr_limit) 123 + : "r" (size), "r" (TASK_SIZE) 100 124 : "cc"); 101 125 102 126 csdb(); ··· 170 194 171 195 #define __get_user_check(x, p) \ 172 196 ({ \ 173 - unsigned long __limit = current_thread_info()->addr_limit - 1; \ 197 + unsigned long __limit = TASK_SIZE - 1; \ 174 198 register typeof(*(p)) __user *__p asm("r0") = (p); \ 175 199 register __inttype(x) __r2 asm("r2"); \ 176 200 register unsigned long __l asm("r1") = __limit; \ ··· 221 245 222 246 #define __put_user_check(__pu_val, __ptr, __err, __s) \ 223 247 ({ \ 224 - unsigned long __limit = current_thread_info()->addr_limit - 1; \ 248 + unsigned long __limit = TASK_SIZE - 1; \ 225 249 register typeof(__pu_val) __r2 asm("r2") = __pu_val; \ 226 250 register const void __user *__p asm("r0") = __ptr; \ 227 251 register unsigned long __l asm("r1") = __limit; \ ··· 238 262 239 263 #else /* CONFIG_MMU */ 240 264 241 - /* 242 - * uClinux has only one addr space, so has simplified address limits. 243 - */ 244 - #define USER_DS KERNEL_DS 245 - 246 - #define uaccess_kernel() (true) 247 265 #define __addr_ok(addr) ((void)(addr), 1) 248 266 #define __range_ok(addr, size) ((void)(addr), 0) 249 - #define get_fs() (KERNEL_DS) 250 - 251 - static inline void set_fs(mm_segment_t fs) 252 - { 253 - } 254 267 255 268 #define get_user(x, p) __get_user(x, p) 256 269 #define __put_user_check __put_user_nocheck ··· 247 282 #endif /* CONFIG_MMU */ 248 283 249 284 #define access_ok(addr, size) (__range_ok(addr, size) == 0) 250 - 251 - #define user_addr_max() \ 252 - (uaccess_kernel() ? ~0UL : get_fs()) 253 285 254 286 #ifdef CONFIG_CPU_SPECTRE 255 287 /*
-2
arch/arm/kernel/asm-offsets.c
··· 43 43 BLANK(); 44 44 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); 45 45 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); 46 - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); 47 46 DEFINE(TI_TASK, offsetof(struct thread_info, task)); 48 47 DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); 49 48 DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); ··· 91 92 DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); 92 93 DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs)); 93 94 DEFINE(SVC_DACR, offsetof(struct svc_pt_regs, dacr)); 94 - DEFINE(SVC_ADDR_LIMIT, offsetof(struct svc_pt_regs, addr_limit)); 95 95 DEFINE(SVC_REGS_SIZE, sizeof(struct svc_pt_regs)); 96 96 BLANK(); 97 97 DEFINE(SIGFRAME_RC3_OFFSET, offsetof(struct sigframe, retcode[3]));
-12
arch/arm/kernel/entry-common.S
··· 49 49 UNWIND(.fnstart ) 50 50 UNWIND(.cantunwind ) 51 51 disable_irq_notrace @ disable interrupts 52 - ldr r2, [tsk, #TI_ADDR_LIMIT] 53 - ldr r1, =TASK_SIZE 54 - cmp r2, r1 55 - blne addr_limit_check_failed 56 52 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 57 53 movs r1, r1, lsl #16 58 54 bne fast_work_pending ··· 83 87 bl do_rseq_syscall 84 88 #endif 85 89 disable_irq_notrace @ disable interrupts 86 - ldr r2, [tsk, #TI_ADDR_LIMIT] 87 - ldr r1, =TASK_SIZE 88 - cmp r2, r1 89 - blne addr_limit_check_failed 90 90 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 91 91 movs r1, r1, lsl #16 92 92 beq no_work_pending ··· 121 129 #endif 122 130 disable_irq_notrace @ disable interrupts 123 131 ENTRY(ret_to_user_from_irq) 124 - ldr r2, [tsk, #TI_ADDR_LIMIT] 125 - ldr r1, =TASK_SIZE 126 - cmp r2, r1 127 - blne addr_limit_check_failed 128 132 ldr r1, [tsk, #TI_FLAGS] 129 133 movs r1, r1, lsl #16 130 134 bne slow_work_pending
+1 -6
arch/arm/kernel/process.c
··· 108 108 unsigned long flags; 109 109 char buf[64]; 110 110 #ifndef CONFIG_CPU_V7M 111 - unsigned int domain, fs; 111 + unsigned int domain; 112 112 #ifdef CONFIG_CPU_SW_DOMAIN_PAN 113 113 /* 114 114 * Get the domain register for the parent context. In user ··· 117 117 */ 118 118 if (user_mode(regs)) { 119 119 domain = DACR_UACCESS_ENABLE; 120 - fs = get_fs(); 121 120 } else { 122 121 domain = to_svc_pt_regs(regs)->dacr; 123 - fs = to_svc_pt_regs(regs)->addr_limit; 124 122 } 125 123 #else 126 124 domain = get_domain(); 127 - fs = get_fs(); 128 125 #endif 129 126 #endif 130 127 ··· 157 160 if ((domain & domain_mask(DOMAIN_USER)) == 158 161 domain_val(DOMAIN_USER, DOMAIN_NOACCESS)) 159 162 segment = "none"; 160 - else if (fs == KERNEL_DS) 161 - segment = "kernel"; 162 163 else 163 164 segment = "user"; 164 165
-8
arch/arm/kernel/signal.c
··· 711 711 return page; 712 712 } 713 713 714 - /* Defer to generic check */ 715 - asmlinkage void addr_limit_check_failed(void) 716 - { 717 - #ifdef CONFIG_MMU 718 - addr_limit_user_check(); 719 - #endif 720 - } 721 - 722 714 #ifdef CONFIG_DEBUG_RSEQ 723 715 asmlinkage void do_rseq_syscall(struct pt_regs *regs) 724 716 {
+1 -2
arch/arm/lib/copy_from_user.S
··· 109 109 110 110 ENTRY(arm_copy_from_user) 111 111 #ifdef CONFIG_CPU_SPECTRE 112 - get_thread_info r3 113 - ldr r3, [r3, #TI_ADDR_LIMIT] 112 + ldr r3, =TASK_SIZE 114 113 uaccess_mask_range_ptr r1, r2, r3, ip 115 114 #endif 116 115
+1 -2
arch/arm/lib/copy_to_user.S
··· 109 109 ENTRY(__copy_to_user_std) 110 110 WEAK(arm_copy_to_user) 111 111 #ifdef CONFIG_CPU_SPECTRE 112 - get_thread_info r3 113 - ldr r3, [r3, #TI_ADDR_LIMIT] 112 + ldr r3, =TASK_SIZE 114 113 uaccess_mask_range_ptr r0, r2, r3, ip 115 114 #endif 116 115