aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-12-07 11:34:37 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-12-10 19:18:26 -0500
commitb10bca0bc699af201770989a88fa293155e9d8de (patch)
tree7e9a997cd61232170a37bca7e99b170965991f41
parent39b175a0092d4a8e0875c67df82285475b1da591 (diff)
ARM: 7595/1: syscall: rework ordering in syscall_trace_exit
syscall_trace_exit is currently doing things back-to-front; invoking the audit hook *after* signalling the debugger, which presents an opportunity for the registers to be re-written by userspace in order to bypass auditing constaints. This patch fixes the ordering by moving the audit code first and the tracehook code last. On the face of it, it looks like current_thread_info()->syscall may be incorrect for the sys_exit tracepoint, but that's actually not an issue because it will have been set during syscall entry and cannot have changed since then. Reported-by: Andrew Gabbasov <Andrew_Gabbasov@mentor.com> Tested-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/kernel/entry-common.S1
-rw-r--r--arch/arm/kernel/ptrace.c24
2 files changed, 15 insertions, 10 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index ee81dbc6fa10..d863bbf0f1f5 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -455,7 +455,6 @@ __sys_trace:
455 455
456__sys_trace_return: 456__sys_trace_return:
457 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 457 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
458 mov r1, scno
459 mov r0, sp 458 mov r0, sp
460 bl syscall_trace_exit 459 bl syscall_trace_exit
461 b ret_slow_syscall 460 b ret_slow_syscall
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 518536d93fba..03deeffd9f6d 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -957,17 +957,23 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
957 return scno; 957 return scno;
958} 958}
959 959
960asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) 960asmlinkage void syscall_trace_exit(struct pt_regs *regs)
961{ 961{
962 current_thread_info()->syscall = scno; 962 /*
963 963 * Audit the syscall before anything else, as a debugger may
964 if (test_thread_flag(TIF_SYSCALL_TRACE)) 964 * come in and change the current registers.
965 scno = tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT); 965 */
966 audit_syscall_exit(regs);
966 967
968 /*
969 * Note that we haven't updated the ->syscall field for the
970 * current thread. This isn't a problem because it will have
971 * been set on syscall entry and there hasn't been an opportunity
972 * for a PTRACE_SET_SYSCALL since then.
973 */
967 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) 974 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
968 trace_sys_exit(regs, scno); 975 trace_sys_exit(regs, regs_return_value(regs));
969
970 audit_syscall_exit(regs);
971 976
972 return scno; 977 if (test_thread_flag(TIF_SYSCALL_TRACE))
978 tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
973} 979}