diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2013-02-14 12:44:23 -0500 |
---|---|---|
committer | Michael Ellerman <michael@ellerman.id.au> | 2013-04-17 23:03:57 -0400 |
commit | ee4a3916614829914830bc4371358f4d4a63c4d9 (patch) | |
tree | ba1c65ba0a58933b8d9d43fe0374bdbc775338ad /arch/powerpc | |
parent | 3cc33d50f52521760da29ebd9db239741da7f21a (diff) |
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: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/ptrace.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 29 | ||||
-rw-r--r-- | arch/powerpc/kernel/ptrace32.c | 15 |
3 files changed, 32 insertions, 15 deletions
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 5f995681bc1d..becc08e6a65c 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h | |||
@@ -92,7 +92,8 @@ static inline long regs_return_value(struct pt_regs *regs) | |||
92 | } while(0) | 92 | } while(0) |
93 | 93 | ||
94 | struct task_struct; | 94 | struct task_struct; |
95 | extern unsigned long ptrace_get_reg(struct task_struct *task, int regno); | 95 | extern int ptrace_get_reg(struct task_struct *task, int regno, |
96 | unsigned long *data); | ||
96 | extern int ptrace_put_reg(struct task_struct *task, int regno, | 97 | extern int ptrace_put_reg(struct task_struct *task, int regno, |
97 | unsigned long data); | 98 | unsigned long data); |
98 | 99 | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index f9b30c68ba47..10ade3c0c88a 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -180,9 +180,10 @@ static int set_user_msr(struct task_struct *task, unsigned long msr) | |||
180 | } | 180 | } |
181 | 181 | ||
182 | #ifdef CONFIG_PPC64 | 182 | #ifdef CONFIG_PPC64 |
183 | static unsigned long get_user_dscr(struct task_struct *task) | 183 | static int get_user_dscr(struct task_struct *task, unsigned long *data) |
184 | { | 184 | { |
185 | return task->thread.dscr; | 185 | *data = task->thread.dscr; |
186 | return 0; | ||
186 | } | 187 | } |
187 | 188 | ||
188 | static int set_user_dscr(struct task_struct *task, unsigned long dscr) | 189 | 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 | return 0; | 193 | return 0; |
193 | } | 194 | } |
194 | #else | 195 | #else |
195 | static unsigned long get_user_dscr(struct task_struct *task) | 196 | static int get_user_dscr(struct task_struct *task, unsigned long *data) |
196 | { | 197 | { |
197 | return -EIO; | 198 | return -EIO; |
198 | } | 199 | } |
@@ -216,19 +217,23 @@ static int set_user_trap(struct task_struct *task, unsigned long trap) | |||
216 | /* | 217 | /* |
217 | * Get contents of register REGNO in task TASK. | 218 | * Get contents of register REGNO in task TASK. |
218 | */ | 219 | */ |
219 | unsigned long ptrace_get_reg(struct task_struct *task, int regno) | 220 | int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data) |
220 | { | 221 | { |
221 | if (task->thread.regs == NULL) | 222 | if ((task->thread.regs == NULL) || !data) |
222 | return -EIO; | 223 | return -EIO; |
223 | 224 | ||
224 | if (regno == PT_MSR) | 225 | if (regno == PT_MSR) { |
225 | return get_user_msr(task); | 226 | *data = get_user_msr(task); |
227 | return 0; | ||
228 | } | ||
226 | 229 | ||
227 | if (regno == PT_DSCR) | 230 | if (regno == PT_DSCR) |
228 | return get_user_dscr(task); | 231 | return get_user_dscr(task, data); |
229 | 232 | ||
230 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) | 233 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { |
231 | return ((unsigned long *)task->thread.regs)[regno]; | 234 | *data = ((unsigned long *)task->thread.regs)[regno]; |
235 | return 0; | ||
236 | } | ||
232 | 237 | ||
233 | return -EIO; | 238 | return -EIO; |
234 | } | 239 | } |
@@ -1560,7 +1565,9 @@ long arch_ptrace(struct task_struct *child, long request, | |||
1560 | 1565 | ||
1561 | CHECK_FULL_REGS(child->thread.regs); | 1566 | CHECK_FULL_REGS(child->thread.regs); |
1562 | if (index < PT_FPR0) { | 1567 | if (index < PT_FPR0) { |
1563 | tmp = ptrace_get_reg(child, (int) index); | 1568 | ret = ptrace_get_reg(child, (int) index, &tmp); |
1569 | if (ret) | ||
1570 | break; | ||
1564 | } else { | 1571 | } else { |
1565 | unsigned int fpidx = index - PT_FPR0; | 1572 | unsigned int fpidx = index - PT_FPR0; |
1566 | 1573 | ||
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index c0244e766834..f51599e941c7 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -95,7 +95,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
95 | 95 | ||
96 | CHECK_FULL_REGS(child->thread.regs); | 96 | CHECK_FULL_REGS(child->thread.regs); |
97 | if (index < PT_FPR0) { | 97 | if (index < PT_FPR0) { |
98 | tmp = ptrace_get_reg(child, index); | 98 | ret = ptrace_get_reg(child, index, &tmp); |
99 | if (ret) | ||
100 | break; | ||
99 | } else { | 101 | } else { |
100 | flush_fp_to_thread(child); | 102 | flush_fp_to_thread(child); |
101 | /* | 103 | /* |
@@ -148,7 +150,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
148 | tmp = ((u64 *)child->thread.fpr) | 150 | tmp = ((u64 *)child->thread.fpr) |
149 | [FPRINDEX_3264(numReg)]; | 151 | [FPRINDEX_3264(numReg)]; |
150 | } else { /* register within PT_REGS struct */ | 152 | } else { /* register within PT_REGS struct */ |
151 | tmp = ptrace_get_reg(child, numReg); | 153 | unsigned long tmp2; |
154 | ret = ptrace_get_reg(child, numReg, &tmp2); | ||
155 | if (ret) | ||
156 | break; | ||
157 | tmp = tmp2; | ||
152 | } | 158 | } |
153 | reg32bits = ((u32*)&tmp)[part]; | 159 | reg32bits = ((u32*)&tmp)[part]; |
154 | ret = put_user(reg32bits, (u32 __user *)data); | 160 | ret = put_user(reg32bits, (u32 __user *)data); |
@@ -232,7 +238,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
232 | break; | 238 | break; |
233 | CHECK_FULL_REGS(child->thread.regs); | 239 | CHECK_FULL_REGS(child->thread.regs); |
234 | if (numReg < PT_FPR0) { | 240 | if (numReg < PT_FPR0) { |
235 | unsigned long freg = ptrace_get_reg(child, numReg); | 241 | unsigned long freg; |
242 | ret = ptrace_get_reg(child, numReg, &freg); | ||
243 | if (ret) | ||
244 | break; | ||
236 | if (index % 2) | 245 | if (index % 2) |
237 | freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); | 246 | freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); |
238 | else | 247 | else |