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

arm64: Rework valid_user_regs

We validate pstate using PSR_MODE32_BIT, which is part of the
user-provided pstate (and cannot be trusted). Also, we conflate
validation of AArch32 and AArch64 pstate values, making the code
difficult to reason about.

Instead, validate the pstate value based on the associated task. The
task may or may not be current (e.g. when using ptrace), so this must be
passed explicitly by callers. To avoid circular header dependencies via
sched.h, is_compat_task is pulled out of asm/ptrace.h.

To make the code possible to reason about, the AArch64 and AArch32
validation is split into separate functions. Software must respect the
RES0 policy for SPSR bits, and thus the kernel mirrors the hardware
policy (RAZ/WI) for bits as-yet unallocated. When these acquire an
architected meaning writes may be permitted (potentially with additional
validation).

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Rutland and committed by
Catalin Marinas
dbd4d7ca 6d2aa549

+85 -34
+4 -29
arch/arm64/include/asm/ptrace.h
··· 58 58 #define COMPAT_PSR_Z_BIT 0x40000000 59 59 #define COMPAT_PSR_N_BIT 0x80000000 60 60 #define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */ 61 + #define COMPAT_PSR_GE_MASK 0x000f0000 61 62 62 63 #ifdef CONFIG_CPU_BIG_ENDIAN 63 64 #define COMPAT_PSR_ENDSTATE COMPAT_PSR_E_BIT ··· 152 151 return regs->regs[0]; 153 152 } 154 153 155 - /* 156 - * Are the current registers suitable for user mode? (used to maintain 157 - * security in signal handlers) 158 - */ 159 - static inline int valid_user_regs(struct user_pt_regs *regs) 160 - { 161 - if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) { 162 - regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT); 163 - 164 - /* The T bit is reserved for AArch64 */ 165 - if (!(regs->pstate & PSR_MODE32_BIT)) 166 - regs->pstate &= ~COMPAT_PSR_T_BIT; 167 - 168 - return 1; 169 - } 170 - 171 - /* 172 - * Force PSR to something logical... 173 - */ 174 - regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \ 175 - COMPAT_PSR_T_BIT | PSR_MODE32_BIT; 176 - 177 - if (!(regs->pstate & PSR_MODE32_BIT)) { 178 - regs->pstate &= ~COMPAT_PSR_T_BIT; 179 - regs->pstate |= PSR_MODE_EL0t; 180 - } 181 - 182 - return 0; 183 - } 154 + /* We must avoid circular header include via sched.h */ 155 + struct task_struct; 156 + int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task); 184 157 185 158 #define instruction_pointer(regs) ((unsigned long)(regs)->pc) 186 159
+78 -2
arch/arm64/kernel/ptrace.c
··· 500 500 if (ret) 501 501 return ret; 502 502 503 - if (!valid_user_regs(&newregs)) 503 + if (!valid_user_regs(&newregs, target)) 504 504 return -EINVAL; 505 505 506 506 task_pt_regs(target)->user_regs = newregs; ··· 770 770 771 771 } 772 772 773 - if (valid_user_regs(&newregs.user_regs)) 773 + if (valid_user_regs(&newregs.user_regs, target)) 774 774 *task_pt_regs(target) = newregs; 775 775 else 776 776 ret = -EINVAL; ··· 1271 1271 1272 1272 if (test_thread_flag(TIF_SYSCALL_TRACE)) 1273 1273 tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT); 1274 + } 1275 + 1276 + /* 1277 + * Bits which are always architecturally RES0 per ARM DDI 0487A.h 1278 + * Userspace cannot use these until they have an architectural meaning. 1279 + * We also reserve IL for the kernel; SS is handled dynamically. 1280 + */ 1281 + #define SPSR_EL1_AARCH64_RES0_BITS \ 1282 + (GENMASK_ULL(63,32) | GENMASK_ULL(27, 22) | GENMASK_ULL(20, 10) | \ 1283 + GENMASK_ULL(5, 5)) 1284 + #define SPSR_EL1_AARCH32_RES0_BITS \ 1285 + (GENMASK_ULL(63,32) | GENMASK_ULL(24, 22) | GENMASK_ULL(20,20)) 1286 + 1287 + static int valid_compat_regs(struct user_pt_regs *regs) 1288 + { 1289 + regs->pstate &= ~SPSR_EL1_AARCH32_RES0_BITS; 1290 + 1291 + if (!system_supports_mixed_endian_el0()) { 1292 + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) 1293 + regs->pstate |= COMPAT_PSR_E_BIT; 1294 + else 1295 + regs->pstate &= ~COMPAT_PSR_E_BIT; 1296 + } 1297 + 1298 + if (user_mode(regs) && (regs->pstate & PSR_MODE32_BIT) && 1299 + (regs->pstate & COMPAT_PSR_A_BIT) == 0 && 1300 + (regs->pstate & COMPAT_PSR_I_BIT) == 0 && 1301 + (regs->pstate & COMPAT_PSR_F_BIT) == 0) { 1302 + return 1; 1303 + } 1304 + 1305 + /* 1306 + * Force PSR to a valid 32-bit EL0t, preserving the same bits as 1307 + * arch/arm. 1308 + */ 1309 + regs->pstate &= COMPAT_PSR_N_BIT | COMPAT_PSR_Z_BIT | 1310 + COMPAT_PSR_C_BIT | COMPAT_PSR_V_BIT | 1311 + COMPAT_PSR_Q_BIT | COMPAT_PSR_IT_MASK | 1312 + COMPAT_PSR_GE_MASK | COMPAT_PSR_E_BIT | 1313 + COMPAT_PSR_T_BIT; 1314 + regs->pstate |= PSR_MODE32_BIT; 1315 + 1316 + return 0; 1317 + } 1318 + 1319 + static int valid_native_regs(struct user_pt_regs *regs) 1320 + { 1321 + regs->pstate &= ~SPSR_EL1_AARCH64_RES0_BITS; 1322 + 1323 + if (user_mode(regs) && !(regs->pstate & PSR_MODE32_BIT) && 1324 + (regs->pstate & PSR_D_BIT) == 0 && 1325 + (regs->pstate & PSR_A_BIT) == 0 && 1326 + (regs->pstate & PSR_I_BIT) == 0 && 1327 + (regs->pstate & PSR_F_BIT) == 0) { 1328 + return 1; 1329 + } 1330 + 1331 + /* Force PSR to a valid 64-bit EL0t */ 1332 + regs->pstate &= PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT; 1333 + 1334 + return 0; 1335 + } 1336 + 1337 + /* 1338 + * Are the current registers suitable for user mode? (used to maintain 1339 + * security in signal handlers) 1340 + */ 1341 + int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task) 1342 + { 1343 + if (!test_tsk_thread_flag(task, TIF_SINGLESTEP)) 1344 + regs->pstate &= ~DBG_SPSR_SS; 1345 + 1346 + if (is_compat_thread(task_thread_info(task))) 1347 + return valid_compat_regs(regs); 1348 + else 1349 + return valid_native_regs(regs); 1274 1350 }
+2 -2
arch/arm64/kernel/signal.c
··· 115 115 */ 116 116 regs->syscallno = ~0UL; 117 117 118 - err |= !valid_user_regs(&regs->user_regs); 118 + err |= !valid_user_regs(&regs->user_regs, current); 119 119 120 120 if (err == 0) { 121 121 struct fpsimd_context *fpsimd_ctx = ··· 307 307 /* 308 308 * Check that the resulting registers are actually sane. 309 309 */ 310 - ret |= !valid_user_regs(&regs->user_regs); 310 + ret |= !valid_user_regs(&regs->user_regs, current); 311 311 312 312 /* 313 313 * Fast forward the stepping logic so we step into the signal
+1 -1
arch/arm64/kernel/signal32.c
··· 356 356 */ 357 357 regs->syscallno = ~0UL; 358 358 359 - err |= !valid_user_regs(&regs->user_regs); 359 + err |= !valid_user_regs(&regs->user_regs, current); 360 360 361 361 aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace; 362 362 if (err == 0)