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

MIPS: scall: Save thread_info.syscall unconditionally on entry

thread_info.syscall is used by syscall_get_nr to supply syscall nr
over a thread stack frame.

Previously, thread_info.syscall is only saved at syscall_trace_enter
when syscall tracing is enabled. However rest of the kernel code do
expect syscall_get_nr to be available without syscall tracing. The
previous design breaks collect_syscall.

Move saving process to syscall entry to fix it.

Reported-by: Xi Ruoyao <xry111@xry111.site>
Link: https://github.com/util-linux/util-linux/issues/2867
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Jiaxun Yang and committed by
Thomas Bogendoerfer
4370b673 4cece764

+42 -38
+1 -1
arch/mips/include/asm/ptrace.h
··· 159 159 #define exception_ip(regs) exception_ip(regs) 160 160 #define profile_pc(regs) instruction_pointer(regs) 161 161 162 - extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall); 162 + extern asmlinkage long syscall_trace_enter(struct pt_regs *regs); 163 163 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); 164 164 165 165 extern void die(const char *, struct pt_regs *) __noreturn;
+1
arch/mips/kernel/asm-offsets.c
··· 101 101 OFFSET(TI_CPU, thread_info, cpu); 102 102 OFFSET(TI_PRE_COUNT, thread_info, preempt_count); 103 103 OFFSET(TI_REGS, thread_info, regs); 104 + OFFSET(TI_SYSCALL, thread_info, syscall); 104 105 DEFINE(_THREAD_SIZE, THREAD_SIZE); 105 106 DEFINE(_THREAD_MASK, THREAD_MASK); 106 107 DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
+6 -9
arch/mips/kernel/ptrace.c
··· 1317 1317 * Notification of system call entry/exit 1318 1318 * - triggered by current->work.syscall_trace 1319 1319 */ 1320 - asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) 1320 + asmlinkage long syscall_trace_enter(struct pt_regs *regs) 1321 1321 { 1322 1322 user_exit(); 1323 - 1324 - current_thread_info()->syscall = syscall; 1325 1323 1326 1324 if (test_thread_flag(TIF_SYSCALL_TRACE)) { 1327 1325 if (ptrace_report_syscall_entry(regs)) 1328 1326 return -1; 1329 - syscall = current_thread_info()->syscall; 1330 1327 } 1331 1328 1332 1329 #ifdef CONFIG_SECCOMP ··· 1332 1335 struct seccomp_data sd; 1333 1336 unsigned long args[6]; 1334 1337 1335 - sd.nr = syscall; 1338 + sd.nr = current_thread_info()->syscall; 1336 1339 sd.arch = syscall_get_arch(current); 1337 1340 syscall_get_arguments(current, regs, args); 1338 1341 for (i = 0; i < 6; i++) ··· 1342 1345 ret = __secure_computing(&sd); 1343 1346 if (ret == -1) 1344 1347 return ret; 1345 - syscall = current_thread_info()->syscall; 1346 1348 } 1347 1349 #endif 1348 1350 1349 1351 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1350 1352 trace_sys_enter(regs, regs->regs[2]); 1351 1353 1352 - audit_syscall_entry(syscall, regs->regs[4], regs->regs[5], 1354 + audit_syscall_entry(current_thread_info()->syscall, 1355 + regs->regs[4], regs->regs[5], 1353 1356 regs->regs[6], regs->regs[7]); 1354 1357 1355 1358 /* 1356 1359 * Negative syscall numbers are mistaken for rejected syscalls, but 1357 1360 * won't have had the return value set appropriately, so we do so now. 1358 1361 */ 1359 - if (syscall < 0) 1362 + if (current_thread_info()->syscall < 0) 1360 1363 syscall_set_return_value(current, regs, -ENOSYS, 0); 1361 - return syscall; 1364 + return current_thread_info()->syscall; 1362 1365 } 1363 1366 1364 1367 /*
+13 -10
arch/mips/kernel/scall32-o32.S
··· 77 77 PTR_WD load_a7, bad_stack_a7 78 78 .previous 79 79 80 + /* 81 + * syscall number is in v0 unless we called syscall(__NR_###) 82 + * where the real syscall number is in a0 83 + */ 84 + subu t2, v0, __NR_O32_Linux 85 + bnez t2, 1f /* __NR_syscall at offset 0 */ 86 + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number 87 + b 2f 88 + 1: 89 + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number 90 + 2: 91 + 80 92 lw t0, TI_FLAGS($28) # syscall tracing enabled? 81 93 li t1, _TIF_WORK_SYSCALL_ENTRY 82 94 and t0, t1 ··· 126 114 SAVE_STATIC 127 115 move a0, sp 128 116 129 - /* 130 - * syscall number is in v0 unless we called syscall(__NR_###) 131 - * where the real syscall number is in a0 132 - */ 133 - move a1, v0 134 - subu t2, v0, __NR_O32_Linux 135 - bnez t2, 1f /* __NR_syscall at offset 0 */ 136 - lw a1, PT_R4(sp) 137 - 138 - 1: jal syscall_trace_enter 117 + jal syscall_trace_enter 139 118 140 119 bltz v0, 1f # seccomp failed? Skip syscall 141 120
+2 -1
arch/mips/kernel/scall64-n32.S
··· 44 44 45 45 sd a3, PT_R26(sp) # save a3 for syscall restarting 46 46 47 + LONG_S v0, TI_SYSCALL($28) # Store syscall number 48 + 47 49 li t1, _TIF_WORK_SYSCALL_ENTRY 48 50 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? 49 51 and t0, t1, t0 ··· 74 72 n32_syscall_trace_entry: 75 73 SAVE_STATIC 76 74 move a0, sp 77 - move a1, v0 78 75 jal syscall_trace_enter 79 76 80 77 bltz v0, 1f # seccomp failed? Skip syscall
+2 -1
arch/mips/kernel/scall64-n64.S
··· 46 46 47 47 sd a3, PT_R26(sp) # save a3 for syscall restarting 48 48 49 + LONG_S v0, TI_SYSCALL($28) # Store syscall number 50 + 49 51 li t1, _TIF_WORK_SYSCALL_ENTRY 50 52 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? 51 53 and t0, t1, t0 ··· 84 82 syscall_trace_entry: 85 83 SAVE_STATIC 86 84 move a0, sp 87 - move a1, v0 88 85 jal syscall_trace_enter 89 86 90 87 bltz v0, 1f # seccomp failed? Skip syscall
+17 -16
arch/mips/kernel/scall64-o32.S
··· 79 79 PTR_WD load_a7, bad_stack_a7 80 80 .previous 81 81 82 + /* 83 + * absolute syscall number is in v0 unless we called syscall(__NR_###) 84 + * where the real syscall number is in a0 85 + * note: NR_syscall is the first O32 syscall but the macro is 86 + * only defined when compiling with -mabi=32 (CONFIG_32BIT) 87 + * therefore __NR_O32_Linux is used (4000) 88 + */ 89 + 90 + subu t2, v0, __NR_O32_Linux 91 + bnez t2, 1f /* __NR_syscall at offset 0 */ 92 + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number 93 + b 2f 94 + 1: 95 + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number 96 + 2: 97 + 82 98 li t1, _TIF_WORK_SYSCALL_ENTRY 83 99 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? 84 100 and t0, t1, t0 ··· 129 113 sd a7, PT_R11(sp) # For indirect syscalls 130 114 131 115 move a0, sp 132 - /* 133 - * absolute syscall number is in v0 unless we called syscall(__NR_###) 134 - * where the real syscall number is in a0 135 - * note: NR_syscall is the first O32 syscall but the macro is 136 - * only defined when compiling with -mabi=32 (CONFIG_32BIT) 137 - * therefore __NR_O32_Linux is used (4000) 138 - */ 139 - .set push 140 - .set reorder 141 - subu t1, v0, __NR_O32_Linux 142 - move a1, v0 143 - bnez t1, 1f /* __NR_syscall at offset 0 */ 144 - ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */ 145 - .set pop 146 - 147 - 1: jal syscall_trace_enter 116 + jal syscall_trace_enter 148 117 149 118 bltz v0, 1f # seccomp failed? Skip syscall 150 119