Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43efb3f0 authored by Jiaxun Yang's avatar Jiaxun Yang Committed by Greg Kroah-Hartman
Browse files

MIPS: scall: Save thread_info.syscall unconditionally on entry



[ Upstream commit 4370b673ccf240bf7587b0cb8e6726a5ccaf1f17 ]

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: default avatarXi Ruoyao <xry111@xry111.site>
Link: https://github.com/util-linux/util-linux/issues/2867


Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarThomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 2cd614ba
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ static inline long regs_return_value(struct pt_regs *regs)
#define instruction_pointer(regs) ((regs)->cp0_epc)
#define profile_pc(regs) instruction_pointer(regs)

extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);

extern void die(const char *, struct pt_regs *) __noreturn;
+1 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ void output_thread_info_defines(void)
	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
	OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
	OFFSET(TI_REGS, thread_info, regs);
	OFFSET(TI_SYSCALL, thread_info, syscall);
	DEFINE(_THREAD_SIZE, THREAD_SIZE);
	DEFINE(_THREAD_MASK, THREAD_MASK);
	DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
+6 −9
Original line number Diff line number Diff line
@@ -1399,16 +1399,13 @@ long arch_ptrace(struct task_struct *child, long request,
 * Notification of system call entry/exit
 * - triggered by current->work.syscall_trace
 */
asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
asmlinkage long syscall_trace_enter(struct pt_regs *regs)
{
	user_exit();

	current_thread_info()->syscall = syscall;

	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
		if (tracehook_report_syscall_entry(regs))
			return -1;
		syscall = current_thread_info()->syscall;
	}

#ifdef CONFIG_SECCOMP
@@ -1417,7 +1414,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
		struct seccomp_data sd;
		unsigned long args[6];

		sd.nr = syscall;
		sd.nr = current_thread_info()->syscall;
		sd.arch = syscall_get_arch(current);
		syscall_get_arguments(current, regs, args);
		for (i = 0; i < 6; i++)
@@ -1427,23 +1424,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
		ret = __secure_computing(&sd);
		if (ret == -1)
			return ret;
		syscall = current_thread_info()->syscall;
	}
#endif

	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
		trace_sys_enter(regs, regs->regs[2]);

	audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
	audit_syscall_entry(current_thread_info()->syscall,
			    regs->regs[4], regs->regs[5],
			    regs->regs[6], regs->regs[7]);

	/*
	 * Negative syscall numbers are mistaken for rejected syscalls, but
	 * won't have had the return value set appropriately, so we do so now.
	 */
	if (syscall < 0)
	if (current_thread_info()->syscall < 0)
		syscall_set_return_value(current, regs, -ENOSYS, 0);
	return syscall;
	return current_thread_info()->syscall;
}

/*
+13 −10
Original line number Diff line number Diff line
@@ -80,6 +80,18 @@ loads_done:
	PTR	load_a7, bad_stack_a7
	.previous

	/*
	 * syscall number is in v0 unless we called syscall(__NR_###)
	 * where the real syscall number is in a0
	 */
	subu	t2, v0,  __NR_O32_Linux
	bnez	t2, 1f /* __NR_syscall at offset 0 */
	LONG_S	a0, TI_SYSCALL($28)	# Save a0 as syscall number
	b	2f
1:
	LONG_S	v0, TI_SYSCALL($28)	# Save v0 as syscall number
2:

	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
	li	t1, _TIF_WORK_SYSCALL_ENTRY
	and	t0, t1
@@ -117,16 +129,7 @@ syscall_trace_entry:
	SAVE_STATIC
	move	a0, sp

	/*
	 * syscall number is in v0 unless we called syscall(__NR_###)
	 * where the real syscall number is in a0
	 */
	move	a1, v0
	subu	t2, v0,  __NR_O32_Linux
	bnez	t2, 1f /* __NR_syscall at offset 0 */
	lw	a1, PT_R4(sp)

1:	jal	syscall_trace_enter
	jal	syscall_trace_enter

	bltz	v0, 1f			# seccomp failed? Skip syscall

+2 −1
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp)

	sd	a3, PT_R26(sp)		# save a3 for syscall restarting

	LONG_S	v0, TI_SYSCALL($28)     # Store syscall number

	li	t1, _TIF_WORK_SYSCALL_ENTRY
	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
	and	t0, t1, t0
@@ -72,7 +74,6 @@ syscall_common:
n32_syscall_trace_entry:
	SAVE_STATIC
	move	a0, sp
	move	a1, v0
	jal	syscall_trace_enter

	bltz	v0, 1f			# seccomp failed? Skip syscall
Loading