arm64: split syscall_trace() into separate functions for enter/exit
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Wed, 30 Apr 2014 09:51:30 +0000 (10:51 +0100)
committerMark Brown <broonie@linaro.org>
Fri, 30 May 2014 17:15:40 +0000 (18:15 +0100)
As done in arm, this change makes it easy to confirm we invoke syscall
related hooks, including syscall tracepoint, audit and seccomp which would
be implemented later, in correct order. That is, undoing operations in the
opposite order on exit that they were done on entry.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
(cherry picked from commit 3157858feff89196635b01495d5ec9ebe206639e)
Signed-off-by: Mark Brown <broonie@linaro.org>
Conflicts:
arch/arm64/kernel/ptrace.c

arch/arm64/kernel/entry.S
arch/arm64/kernel/ptrace.c

index 21dc3415d48810d04c9f272fc28cd9da213347e8..538b826102e3913d4b5d231e7bba22a94b755ce9 100644 (file)
@@ -659,9 +659,8 @@ ENDPROC(el0_svc)
         * switches, and waiting for our parent to respond.
         */
 __sys_trace:
-       mov     x1, sp
-       mov     w0, #0                          // trace entry
-       bl      syscall_trace
+       mov     x0, sp
+       bl      syscall_trace_enter
        adr     lr, __sys_trace_return          // return address
        uxtw    scno, w0                        // syscall number (possibly new)
        mov     x1, sp                          // pointer to regs
@@ -676,9 +675,8 @@ __sys_trace:
 
 __sys_trace_return:
        str     x0, [sp]                        // save returned x0
-       mov     x1, sp
-       mov     w0, #1                          // trace exit
-       bl      syscall_trace
+       mov     x0, sp
+       bl      syscall_trace_exit
        b       ret_to_user
 
 /*
index 5341534b6d04939d444c9c86d5491507d33c9511..b43903472ac7c27c96e3ed3891c854eddaa48378 100644 (file)
@@ -1109,45 +1109,43 @@ long arch_ptrace(struct task_struct *child, long request,
        return ptrace_request(child, request, addr, data);
 }
 
+enum ptrace_syscall_dir {
+       PTRACE_SYSCALL_ENTER = 0,
+       PTRACE_SYSCALL_EXIT,
+};
 
-static int __init ptrace_break_init(void)
-{
-       hook_debug_fault_code(DBG_ESR_EVT_BRK, arm64_break_trap, SIGTRAP,
-                             TRAP_BRKPT, "ptrace BRK handler");
-       return 0;
-}
-core_initcall(ptrace_break_init);
-
-
-asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
+static void tracehook_report_syscall(struct pt_regs *regs,
+                                    enum ptrace_syscall_dir dir)
 {
+       int regno;
        unsigned long saved_reg;
 
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return regs->syscallno;
-
-       if (is_compat_task()) {
-               /* AArch32 uses ip (r12) for scratch */
-               saved_reg = regs->regs[12];
-               regs->regs[12] = dir;
-       } else {
-               /*
-                * Save X7. X7 is used to denote syscall entry/exit:
-                *   X7 = 0 -> entry, = 1 -> exit
-                */
-               saved_reg = regs->regs[7];
-               regs->regs[7] = dir;
-       }
+       /*
+        * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
+        * used to denote syscall entry/exit:
+        */
+       regno = (is_compat_task() ? 12 : 7);
+       saved_reg = regs->regs[regno];
+       regs->regs[regno] = dir;
 
-       if (dir)
+       if (dir == PTRACE_SYSCALL_EXIT)
                tracehook_report_syscall_exit(regs, 0);
        else if (tracehook_report_syscall_entry(regs))
                regs->syscallno = ~0UL;
 
-       if (is_compat_task())
-               regs->regs[12] = saved_reg;
-       else
-               regs->regs[7] = saved_reg;
+       regs->regs[regno] = saved_reg;
+}
+
+asmlinkage int syscall_trace_enter(struct pt_regs *regs)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
 
        return regs->syscallno;
 }
+
+asmlinkage void syscall_trace_exit(struct pt_regs *regs)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
+}