Merge to Fedora kernel-2.6.18-1.2239_FC5 patched with stable patch-2.6.18.2-vs2.0...
[linux-2.6.git] / arch / ppc64 / kernel / ptrace.c
index a8fc80f..4b47ed3 100644 (file)
@@ -27,6 +27,8 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/seccomp.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -103,7 +105,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
                ret = -EIO;
                if (copied != sizeof(tmp))
                        break;
-               ret = put_user(tmp,(unsigned long *) data);
+               ret = put_user(tmp,(unsigned long __user *) data);
                break;
        }
 
@@ -121,11 +123,10 @@ int sys_ptrace(long request, long pid, long addr, long data)
                if (index < PT_FPR0) {
                        tmp = get_reg(child, (int)index);
                } else {
-                       if (child->thread.regs->msr & MSR_FP)
-                               giveup_fpu(child);
+                       flush_fp_to_thread(child);
                        tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
                }
-               ret = put_user(tmp,(unsigned long *) data);
+               ret = put_user(tmp,(unsigned long __user *) data);
                break;
        }
 
@@ -154,8 +155,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
                if (index < PT_FPR0) {
                        ret = put_reg(child, index, data);
                } else {
-                       if (child->thread.regs->msr & MSR_FP)
-                               giveup_fpu(child);
+                       flush_fp_to_thread(child);
                        ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
                        ret = 0;
                }
@@ -165,7 +165,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
        case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
        case PTRACE_CONT: { /* restart after signal. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                if (request == PTRACE_SYSCALL)
                        set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -186,7 +186,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
         */
        case PTRACE_KILL: {
                ret = 0;
-               if (child->state == TASK_ZOMBIE)        /* already dead */
+               if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
                        break;
                child->exit_code = SIGKILL;
                /* make sure the single step bit is not set. */
@@ -197,7 +197,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
 
        case PTRACE_SINGLESTEP: {  /* set the trap flag. */
                ret = -EIO;
-               if ((unsigned long) data > _NSIG)
+               if (!valid_signal(data))
                        break;
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
                set_single_step(child);
@@ -215,7 +215,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
        case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
                int i;
                unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned long *tmp = (unsigned long *)addr;
+               unsigned long __user *tmp = (unsigned long __user *)addr;
 
                for (i = 0; i < 32; i++) {
                        ret = put_user(*reg, tmp);
@@ -230,7 +230,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
        case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
                int i;
                unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
-               unsigned long *tmp = (unsigned long *)addr;
+               unsigned long __user *tmp = (unsigned long __user *)addr;
 
                for (i = 0; i < 32; i++) {
                        ret = get_user(*reg, tmp);
@@ -245,10 +245,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
        case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
                int i;
                unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned long *tmp = (unsigned long *)addr;
+               unsigned long __user *tmp = (unsigned long __user *)addr;
 
-               if (child->thread.regs->msr & MSR_FP)
-                       giveup_fpu(child);
+               flush_fp_to_thread(child);
 
                for (i = 0; i < 32; i++) {
                        ret = put_user(*reg, tmp);
@@ -263,10 +262,9 @@ int sys_ptrace(long request, long pid, long addr, long data)
        case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
                int i;
                unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
-               unsigned long *tmp = (unsigned long *)addr;
+               unsigned long __user *tmp = (unsigned long __user *)addr;
 
-               if (child->thread.regs->msr & MSR_FP)
-                       giveup_fpu(child);
+               flush_fp_to_thread(child);
 
                for (i = 0; i < 32; i++) {
                        ret = get_user(*reg, tmp);
@@ -309,22 +307,30 @@ static void do_syscall_trace(void)
 
 void do_syscall_trace_enter(struct pt_regs *regs)
 {
+       if (test_thread_flag(TIF_SYSCALL_TRACE)
+           && (current->ptrace & PT_PTRACED))
+               do_syscall_trace();
+
        if (unlikely(current->audit_context))
-               audit_syscall_entry(current, regs->gpr[0],
+               audit_syscall_entry(current,
+                                   test_thread_flag(TIF_32BIT)?AUDIT_ARCH_PPC:AUDIT_ARCH_PPC64,
+                                   regs->gpr[0],
                                    regs->gpr[3], regs->gpr[4],
                                    regs->gpr[5], regs->gpr[6]);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
-           && (current->ptrace & PT_PTRACED))
-               do_syscall_trace();
 }
 
-void do_syscall_trace_leave(void)
+void do_syscall_trace_leave(struct pt_regs *regs)
 {
+       secure_computing(regs->gpr[0]);
+
        if (unlikely(current->audit_context))
-               audit_syscall_exit(current, 0); /* FIXME: pass pt_regs */
+               audit_syscall_exit(current, 
+                                  (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+                                  regs->result);
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
+       if ((test_thread_flag(TIF_SYSCALL_TRACE)
+            || test_thread_flag(TIF_SINGLESTEP))
            && (current->ptrace & PT_PTRACED))
                do_syscall_trace();
 }