]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
MIPS: scall: Save thread_info.syscall unconditionally on entry
authorJiaxun Yang <jiaxun.yang@flygoat.com>
Thu, 28 Mar 2024 14:27:56 +0000 (14:27 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 May 2024 09:43:52 +0000 (11:43 +0200)
[ 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>
arch/mips/include/asm/ptrace.h
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-n64.S
arch/mips/kernel/scall64-o32.S

index 2849a9b65a05528decc88839424ca843966cf05b..ae578860f7295ba605c2426246814466aa9b0b57 100644 (file)
@@ -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;
index aebfda81120a1a9c1a1868f8e0eeaf95412d0c6a..6c5269d3aacba353c3932163192c770fbbb6ec52 100644 (file)
@@ -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);
index 414b6e9c900b2c9e455389b9f557d69c16e9c4b2..cfb548fd2712c963718f850cc40b884a06d4cf6e 100644 (file)
@@ -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;
 }
 
 /*
index b449b68662a9aa488400e5b6e86a71ac84d286f1..80747719a35cafbbfb8c0d5413c9158658a38584 100644 (file)
@@ -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
 
index 35d8c86b160ea1b181a2b270fad69b7c18369a26..a8679e34c95e34612e7cb084918bc6eef8f663b0 100644 (file)
@@ -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
index 23b2e2b1609cf72f417c5d82172e53a5a2e03701..a3b5ab509b4120beb9300a65ace5192ffe1b3cbf 100644 (file)
@@ -47,6 +47,8 @@ NESTED(handle_sys64, 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
@@ -83,7 +85,6 @@ n64_syscall_exit:
 syscall_trace_entry:
        SAVE_STATIC
        move    a0, sp
-       move    a1, v0
        jal     syscall_trace_enter
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall
index 41df8221bb8fd4208c445fa0eeddcfc687656d63..d8f41e919c1716320ae3056caf96d9824b209e2e 100644 (file)
@@ -79,6 +79,22 @@ loads_done:
        PTR     load_a7, bad_stack_a7
        .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
        LONG_L  t0, TI_FLAGS($28)       # syscall tracing enabled?
        and     t0, t1, t0
@@ -113,22 +129,7 @@ trace_a_syscall:
        sd      a7, PT_R11(sp)          # For indirect syscalls
 
        move    a0, sp
-       /*
-        * 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
+       jal     syscall_trace_enter
 
        bltz    v0, 1f                  # seccomp failed? Skip syscall