]> git.hungrycats.org Git - linux/commitdiff
ARM: 7411/1: audit: fix treatment of saved ip register during syscall tracing
authorWill Deacon <will.deacon@arm.com>
Fri, 4 May 2012 16:52:02 +0000 (17:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 12 May 2012 16:32:09 +0000 (09:32 -0700)
commit 6a68b6f574c8ad2c1d90f0db8fd95b8abe8a0a73 upstream.

The ARM audit code incorrectly uses the saved application ip register
value to infer syscall entry or exit. Additionally, the saved value will
be clobbered if the current task is not being traced, which can lead to
libc corruption if ip is live (apparently glibc uses it for the TLS
pointer).

This patch fixes the syscall tracing code so that the why parameter is
used to infer the syscall direction and the saved ip is only updated if
we know that we will be signalling a ptrace trap.

Reported-and-Tested-by: Jon Masters <jcm@jonmasters.org>
Cc: Eric Paris <eparis@redhat.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm/kernel/ptrace.c

index ede6443c34d964670560f155aaf200ed6bf0949e..b139270a30fe7be07ef8363caeaabc1be75f2c85 100644 (file)
@@ -915,14 +915,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 {
        unsigned long ip;
 
-       /*
-        * Save IP.  IP is used to denote syscall entry/exit:
-        *  IP = 0 -> entry, = 1 -> exit
-        */
-       ip = regs->ARM_ip;
-       regs->ARM_ip = why;
-
-       if (!ip)
+       if (why)
                audit_syscall_exit(regs);
        else
                audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0,
@@ -935,6 +928,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 
        current_thread_info()->syscall = scno;
 
+       /*
+        * IP is used to denote syscall entry/exit:
+        * IP = 0 -> entry, =1 -> exit
+        */
+       ip = regs->ARM_ip;
+       regs->ARM_ip = why;
+
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)