powerpc: fixing ptrace_get_reg to return an error
authorAlexey Kardashevskiy <aik@ozlabs.ru>
Thu, 14 Feb 2013 17:44:23 +0000 (17:44 +0000)
committerMichael Ellerman <michael@ellerman.id.au>
Thu, 18 Apr 2013 03:03:57 +0000 (13:03 +1000)
Currently ptrace_get_reg returns error as a value
what make impossible to tell whether it is a correct value or error code.

The patch adds a parameter which points to the real return data and
returns an error code.

As get_user_msr() never fails and it is used in multiple places so it has not
been changed by this patch.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/ptrace32.c

index 5f99568..becc08e 100644 (file)
@@ -92,7 +92,8 @@ static inline long regs_return_value(struct pt_regs *regs)
        } while(0)
 
 struct task_struct;
-extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_get_reg(struct task_struct *task, int regno,
+                         unsigned long *data);
 extern int ptrace_put_reg(struct task_struct *task, int regno,
                          unsigned long data);
 
index f9b30c6..10ade3c 100644 (file)
@@ -180,9 +180,10 @@ static int set_user_msr(struct task_struct *task, unsigned long msr)
 }
 
 #ifdef CONFIG_PPC64
-static unsigned long get_user_dscr(struct task_struct *task)
+static int get_user_dscr(struct task_struct *task, unsigned long *data)
 {
-       return task->thread.dscr;
+       *data = task->thread.dscr;
+       return 0;
 }
 
 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
@@ -192,7 +193,7 @@ static int set_user_dscr(struct task_struct *task, unsigned long dscr)
        return 0;
 }
 #else
-static unsigned long get_user_dscr(struct task_struct *task)
+static int get_user_dscr(struct task_struct *task, unsigned long *data)
 {
        return -EIO;
 }
@@ -216,19 +217,23 @@ static int set_user_trap(struct task_struct *task, unsigned long trap)
 /*
  * Get contents of register REGNO in task TASK.
  */
-unsigned long ptrace_get_reg(struct task_struct *task, int regno)
+int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
 {
-       if (task->thread.regs == NULL)
+       if ((task->thread.regs == NULL) || !data)
                return -EIO;
 
-       if (regno == PT_MSR)
-               return get_user_msr(task);
+       if (regno == PT_MSR) {
+               *data = get_user_msr(task);
+               return 0;
+       }
 
        if (regno == PT_DSCR)
-               return get_user_dscr(task);
+               return get_user_dscr(task, data);
 
-       if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
-               return ((unsigned long *)task->thread.regs)[regno];
+       if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
+               *data = ((unsigned long *)task->thread.regs)[regno];
+               return 0;
+       }
 
        return -EIO;
 }
@@ -1560,7 +1565,9 @@ long arch_ptrace(struct task_struct *child, long request,
 
                CHECK_FULL_REGS(child->thread.regs);
                if (index < PT_FPR0) {
-                       tmp = ptrace_get_reg(child, (int) index);
+                       ret = ptrace_get_reg(child, (int) index, &tmp);
+                       if (ret)
+                               break;
                } else {
                        unsigned int fpidx = index - PT_FPR0;
 
index c0244e7..f51599e 100644 (file)
@@ -95,7 +95,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
                CHECK_FULL_REGS(child->thread.regs);
                if (index < PT_FPR0) {
-                       tmp = ptrace_get_reg(child, index);
+                       ret = ptrace_get_reg(child, index, &tmp);
+                       if (ret)
+                               break;
                } else {
                        flush_fp_to_thread(child);
                        /*
@@ -148,7 +150,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        tmp = ((u64 *)child->thread.fpr)
                                [FPRINDEX_3264(numReg)];
                } else { /* register within PT_REGS struct */
-                       tmp = ptrace_get_reg(child, numReg);
+                       unsigned long tmp2;
+                       ret = ptrace_get_reg(child, numReg, &tmp2);
+                       if (ret)
+                               break;
+                       tmp = tmp2;
                } 
                reg32bits = ((u32*)&tmp)[part];
                ret = put_user(reg32bits, (u32 __user *)data);
@@ -232,7 +238,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        break;
                CHECK_FULL_REGS(child->thread.regs);
                if (numReg < PT_FPR0) {
-                       unsigned long freg = ptrace_get_reg(child, numReg);
+                       unsigned long freg;
+                       ret = ptrace_get_reg(child, numReg, &freg);
+                       if (ret)
+                               break;
                        if (index % 2)
                                freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
                        else