mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 07:24:39 +08:00
[POWERPC] Allow ptrace write to pt_regs trap and orig_r3
This patch allows a ptracer to write to the "trap" and "orig_r3" words of the pt_regs. This, along with a subsequent patch to the signal restart code, should enable gdb to properly handle syscall restarting after executing a separate function (at least when there's no restart block). This patch also removes ptrace32.c code toying directly with the registers and makes it use the ptrace_get/put_reg() accessors for everything so that the logic for checking what is permitted is in only one place. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
1b6610d6fc
commit
912000e73e
@ -75,10 +75,15 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
|
|||||||
if (task->thread.regs == NULL)
|
if (task->thread.regs == NULL)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (regno <= PT_MAX_PUT_REG) {
|
if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) {
|
||||||
if (regno == PT_MSR)
|
if (regno == PT_MSR)
|
||||||
data = (data & MSR_DEBUGCHANGE)
|
data = (data & MSR_DEBUGCHANGE)
|
||||||
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
|
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
|
||||||
|
/* We prevent mucking around with the reserved area of trap
|
||||||
|
* which are used internally by the kernel
|
||||||
|
*/
|
||||||
|
if (regno == PT_TRAP)
|
||||||
|
data &= 0xfff0;
|
||||||
((unsigned long *)task->thread.regs)[regno] = data;
|
((unsigned long *)task->thread.regs)[regno] = data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -409,8 +414,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
CHECK_FULL_REGS(child->thread.regs);
|
CHECK_FULL_REGS(child->thread.regs);
|
||||||
if (index == PT_ORIG_R3)
|
|
||||||
break;
|
|
||||||
if (index < PT_FPR0) {
|
if (index < PT_FPR0) {
|
||||||
ret = ptrace_put_reg(child, index, data);
|
ret = ptrace_put_reg(child, index, data);
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,7 +206,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
|
|||||||
else
|
else
|
||||||
part = 0; /* want the 1st half of the register (left-most). */
|
part = 0; /* want the 1st half of the register (left-most). */
|
||||||
|
|
||||||
/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */
|
/* Validate the input - check to see if address is on the wrong boundary
|
||||||
|
* or beyond the end of the user area
|
||||||
|
*/
|
||||||
if ((addr & 3) || numReg > PT_FPSCR)
|
if ((addr & 3) || numReg > PT_FPSCR)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -270,8 +272,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
|
|||||||
if ((addr & 3) || (index > PT_FPSCR32))
|
if ((addr & 3) || (index > PT_FPSCR32))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (index == PT_ORIG_R3)
|
|
||||||
break;
|
|
||||||
if (index < PT_FPR0) {
|
if (index < PT_FPR0) {
|
||||||
ret = ptrace_put_reg(child, index, data);
|
ret = ptrace_put_reg(child, index, data);
|
||||||
} else {
|
} else {
|
||||||
@ -302,24 +302,25 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
|
|||||||
/* Determine which register the user wants */
|
/* Determine which register the user wants */
|
||||||
index = (u64)addr >> 2;
|
index = (u64)addr >> 2;
|
||||||
numReg = index / 2;
|
numReg = index / 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validate the input - check to see if address is on the
|
* Validate the input - check to see if address is on the
|
||||||
* wrong boundary or beyond the end of the user area
|
* wrong boundary or beyond the end of the user area
|
||||||
*/
|
*/
|
||||||
if ((addr & 3) || (numReg > PT_FPSCR))
|
if ((addr & 3) || (numReg > PT_FPSCR))
|
||||||
break;
|
break;
|
||||||
/* Insure it is a register we let them change */
|
if (numReg < PT_FPR0) {
|
||||||
if ((numReg == PT_ORIG_R3)
|
unsigned long freg = ptrace_get_reg(child, numReg);
|
||||||
|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
|
if (index % 2)
|
||||||
break;
|
freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
|
||||||
if (numReg >= PT_FPR0) {
|
else
|
||||||
|
freg = (freg & 0xfffffffful) | (data << 32);
|
||||||
|
ret = ptrace_put_reg(child, numReg, freg);
|
||||||
|
} else {
|
||||||
flush_fp_to_thread(child);
|
flush_fp_to_thread(child);
|
||||||
|
((unsigned int *)child->thread.regs)[index] = data;
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
if (numReg == PT_MSR)
|
|
||||||
data = (data & MSR_DEBUGCHANGE)
|
|
||||||
| (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
|
|
||||||
((u32*)child->thread.regs)[index] = data;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user