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: 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
09888cff32
commit
7c355faad0
@@ -157,7 +157,7 @@ static inline long regs_return_value(struct pt_regs *regs)
|
|||||||
#define instruction_pointer(regs) ((regs)->cp0_epc)
|
#define instruction_pointer(regs) ((regs)->cp0_epc)
|
||||||
#define profile_pc(regs) instruction_pointer(regs)
|
#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 asmlinkage void syscall_trace_leave(struct pt_regs *regs);
|
||||||
|
|
||||||
extern void die(const char *, struct pt_regs *) __noreturn;
|
extern void die(const char *, struct pt_regs *) __noreturn;
|
||||||
|
@@ -100,6 +100,7 @@ void output_thread_info_defines(void)
|
|||||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||||
OFFSET(TI_REGS, thread_info, regs);
|
OFFSET(TI_REGS, thread_info, regs);
|
||||||
|
OFFSET(TI_SYSCALL, thread_info, syscall);
|
||||||
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
||||||
DEFINE(_THREAD_MASK, THREAD_MASK);
|
DEFINE(_THREAD_MASK, THREAD_MASK);
|
||||||
DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
|
DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
|
||||||
|
@@ -1310,16 +1310,13 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||||||
* Notification of system call entry/exit
|
* Notification of system call entry/exit
|
||||||
* - triggered by current->work.syscall_trace
|
* - 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();
|
user_exit();
|
||||||
|
|
||||||
current_thread_info()->syscall = syscall;
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
|
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
|
||||||
if (tracehook_report_syscall_entry(regs))
|
if (tracehook_report_syscall_entry(regs))
|
||||||
return -1;
|
return -1;
|
||||||
syscall = current_thread_info()->syscall;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SECCOMP
|
#ifdef CONFIG_SECCOMP
|
||||||
@@ -1328,7 +1325,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
|
|||||||
struct seccomp_data sd;
|
struct seccomp_data sd;
|
||||||
unsigned long args[6];
|
unsigned long args[6];
|
||||||
|
|
||||||
sd.nr = syscall;
|
sd.nr = current_thread_info()->syscall;
|
||||||
sd.arch = syscall_get_arch(current);
|
sd.arch = syscall_get_arch(current);
|
||||||
syscall_get_arguments(current, regs, args);
|
syscall_get_arguments(current, regs, args);
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
@@ -1338,23 +1335,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
|
|||||||
ret = __secure_computing(&sd);
|
ret = __secure_computing(&sd);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return ret;
|
return ret;
|
||||||
syscall = current_thread_info()->syscall;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||||
trace_sys_enter(regs, regs->regs[2]);
|
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]);
|
regs->regs[6], regs->regs[7]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Negative syscall numbers are mistaken for rejected syscalls, but
|
* Negative syscall numbers are mistaken for rejected syscalls, but
|
||||||
* won't have had the return value set appropriately, so we do so now.
|
* 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);
|
syscall_set_return_value(current, regs, -ENOSYS, 0);
|
||||||
return syscall;
|
return current_thread_info()->syscall;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -80,6 +80,18 @@ loads_done:
|
|||||||
PTR load_a7, bad_stack_a7
|
PTR load_a7, bad_stack_a7
|
||||||
.previous
|
.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?
|
lw t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||||
and t0, t1
|
and t0, t1
|
||||||
@@ -117,16 +129,7 @@ syscall_trace_entry:
|
|||||||
SAVE_STATIC
|
SAVE_STATIC
|
||||||
move a0, sp
|
move a0, sp
|
||||||
|
|
||||||
/*
|
jal syscall_trace_enter
|
||||||
* 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
|
|
||||||
|
|
||||||
bltz v0, 1f # seccomp failed? Skip syscall
|
bltz v0, 1f # seccomp failed? Skip syscall
|
||||||
|
|
||||||
|
@@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp)
|
|||||||
|
|
||||||
sd a3, PT_R26(sp) # save a3 for syscall restarting
|
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
|
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||||
and t0, t1, t0
|
and t0, t1, t0
|
||||||
@@ -72,7 +74,6 @@ syscall_common:
|
|||||||
n32_syscall_trace_entry:
|
n32_syscall_trace_entry:
|
||||||
SAVE_STATIC
|
SAVE_STATIC
|
||||||
move a0, sp
|
move a0, sp
|
||||||
move a1, v0
|
|
||||||
jal syscall_trace_enter
|
jal syscall_trace_enter
|
||||||
|
|
||||||
bltz v0, 1f # seccomp failed? Skip syscall
|
bltz v0, 1f # seccomp failed? Skip syscall
|
||||||
|
@@ -47,6 +47,8 @@ NESTED(handle_sys64, PT_SIZE, sp)
|
|||||||
|
|
||||||
sd a3, PT_R26(sp) # save a3 for syscall restarting
|
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
|
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||||
and t0, t1, t0
|
and t0, t1, t0
|
||||||
@@ -83,7 +85,6 @@ n64_syscall_exit:
|
|||||||
syscall_trace_entry:
|
syscall_trace_entry:
|
||||||
SAVE_STATIC
|
SAVE_STATIC
|
||||||
move a0, sp
|
move a0, sp
|
||||||
move a1, v0
|
|
||||||
jal syscall_trace_enter
|
jal syscall_trace_enter
|
||||||
|
|
||||||
bltz v0, 1f # seccomp failed? Skip syscall
|
bltz v0, 1f # seccomp failed? Skip syscall
|
||||||
|
@@ -79,6 +79,22 @@ loads_done:
|
|||||||
PTR load_a7, bad_stack_a7
|
PTR load_a7, bad_stack_a7
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
/*
|
||||||
|
* absolute syscall number is in v0 unless we called syscall(__NR_###)
|
||||||
|
* where the real syscall number is in a0
|
||||||
|
* note: NR_syscall is the first O32 syscall but the macro is
|
||||||
|
* only defined when compiling with -mabi=32 (CONFIG_32BIT)
|
||||||
|
* therefore __NR_O32_Linux is used (4000)
|
||||||
|
*/
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
li t1, _TIF_WORK_SYSCALL_ENTRY
|
li t1, _TIF_WORK_SYSCALL_ENTRY
|
||||||
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
|
||||||
and t0, t1, t0
|
and t0, t1, t0
|
||||||
@@ -113,22 +129,7 @@ trace_a_syscall:
|
|||||||
sd a7, PT_R11(sp) # For indirect syscalls
|
sd a7, PT_R11(sp) # For indirect syscalls
|
||||||
|
|
||||||
move a0, sp
|
move a0, sp
|
||||||
/*
|
jal syscall_trace_enter
|
||||||
* absolute syscall number is in v0 unless we called syscall(__NR_###)
|
|
||||||
* where the real syscall number is in a0
|
|
||||||
* note: NR_syscall is the first O32 syscall but the macro is
|
|
||||||
* only defined when compiling with -mabi=32 (CONFIG_32BIT)
|
|
||||||
* therefore __NR_O32_Linux is used (4000)
|
|
||||||
*/
|
|
||||||
.set push
|
|
||||||
.set reorder
|
|
||||||
subu t1, v0, __NR_O32_Linux
|
|
||||||
move a1, v0
|
|
||||||
bnez t1, 1f /* __NR_syscall at offset 0 */
|
|
||||||
ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
|
|
||||||
.set pop
|
|
||||||
|
|
||||||
1: jal syscall_trace_enter
|
|
||||||
|
|
||||||
bltz v0, 1f # seccomp failed? Skip syscall
|
bltz v0, 1f # seccomp failed? Skip syscall
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user