Commit ee4a3916 authored by Alexey Kardashevskiy's avatar Alexey Kardashevskiy Committed by Michael Ellerman

powerpc: fixing ptrace_get_reg to return an error

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: default avatarAlexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: default avatarMichael Neuling <mikey@neuling.org>
Signed-off-by: default avatarMichael Ellerman <michael@ellerman.id.au>
parent 3cc33d50
...@@ -92,7 +92,8 @@ static inline long regs_return_value(struct pt_regs *regs) ...@@ -92,7 +92,8 @@ static inline long regs_return_value(struct pt_regs *regs)
} while(0) } while(0)
struct task_struct; 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, extern int ptrace_put_reg(struct task_struct *task, int regno,
unsigned long data); unsigned long data);
......
...@@ -180,9 +180,10 @@ static int set_user_msr(struct task_struct *task, unsigned long msr) ...@@ -180,9 +180,10 @@ static int set_user_msr(struct task_struct *task, unsigned long msr)
} }
#ifdef CONFIG_PPC64 #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) 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) ...@@ -192,7 +193,7 @@ static int set_user_dscr(struct task_struct *task, unsigned long dscr)
return 0; return 0;
} }
#else #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; return -EIO;
} }
...@@ -216,19 +217,23 @@ static int set_user_trap(struct task_struct *task, unsigned long trap) ...@@ -216,19 +217,23 @@ static int set_user_trap(struct task_struct *task, unsigned long trap)
/* /*
* Get contents of register REGNO in task TASK. * 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; return -EIO;
if (regno == PT_MSR) if (regno == PT_MSR) {
return get_user_msr(task); *data = get_user_msr(task);
return 0;
}
if (regno == PT_DSCR) if (regno == PT_DSCR)
return get_user_dscr(task); return get_user_dscr(task, data);
if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
return ((unsigned long *)task->thread.regs)[regno]; *data = ((unsigned long *)task->thread.regs)[regno];
return 0;
}
return -EIO; return -EIO;
} }
...@@ -1560,7 +1565,9 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -1560,7 +1565,9 @@ long arch_ptrace(struct task_struct *child, long request,
CHECK_FULL_REGS(child->thread.regs); CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = ptrace_get_reg(child, (int) index); ret = ptrace_get_reg(child, (int) index, &tmp);
if (ret)
break;
} else { } else {
unsigned int fpidx = index - PT_FPR0; unsigned int fpidx = index - PT_FPR0;
......
...@@ -95,7 +95,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -95,7 +95,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
CHECK_FULL_REGS(child->thread.regs); CHECK_FULL_REGS(child->thread.regs);
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = ptrace_get_reg(child, index); ret = ptrace_get_reg(child, index, &tmp);
if (ret)
break;
} else { } else {
flush_fp_to_thread(child); flush_fp_to_thread(child);
/* /*
...@@ -148,7 +150,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -148,7 +150,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
tmp = ((u64 *)child->thread.fpr) tmp = ((u64 *)child->thread.fpr)
[FPRINDEX_3264(numReg)]; [FPRINDEX_3264(numReg)];
} else { /* register within PT_REGS struct */ } 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]; reg32bits = ((u32*)&tmp)[part];
ret = put_user(reg32bits, (u32 __user *)data); ret = put_user(reg32bits, (u32 __user *)data);
...@@ -232,7 +238,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -232,7 +238,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break; break;
CHECK_FULL_REGS(child->thread.regs); CHECK_FULL_REGS(child->thread.regs);
if (numReg < PT_FPR0) { 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) if (index % 2)
freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment