arm64: ptrace: fix compat registes get/set to be endian clean
On a BE system the wrong half of the X registers is retrieved/written when attempting to get/set the value of aarch32 registers through ptrace. Ensure that types are the correct width so that the relevant casting occurs. Signed-off-by: Matthew Leach <matthew.leach@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
b3bf6aa7e7
commit
6a2e5e521c
|
@ -636,28 +636,27 @@ static int compat_gpr_get(struct task_struct *target,
|
||||||
|
|
||||||
for (i = 0; i < num_regs; ++i) {
|
for (i = 0; i < num_regs; ++i) {
|
||||||
unsigned int idx = start + i;
|
unsigned int idx = start + i;
|
||||||
void *reg;
|
compat_ulong_t reg;
|
||||||
|
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 15:
|
case 15:
|
||||||
reg = (void *)&task_pt_regs(target)->pc;
|
reg = task_pt_regs(target)->pc;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
reg = (void *)&task_pt_regs(target)->pstate;
|
reg = task_pt_regs(target)->pstate;
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
reg = (void *)&task_pt_regs(target)->orig_x0;
|
reg = task_pt_regs(target)->orig_x0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reg = (void *)&task_pt_regs(target)->regs[idx];
|
reg = task_pt_regs(target)->regs[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t));
|
ret = copy_to_user(ubuf, ®, sizeof(reg));
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
else
|
|
||||||
ubuf += sizeof(compat_ulong_t);
|
ubuf += sizeof(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -685,28 +684,28 @@ static int compat_gpr_set(struct task_struct *target,
|
||||||
|
|
||||||
for (i = 0; i < num_regs; ++i) {
|
for (i = 0; i < num_regs; ++i) {
|
||||||
unsigned int idx = start + i;
|
unsigned int idx = start + i;
|
||||||
void *reg;
|
compat_ulong_t reg;
|
||||||
|
|
||||||
|
ret = copy_from_user(®, ubuf, sizeof(reg));
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ubuf += sizeof(reg);
|
||||||
|
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 15:
|
case 15:
|
||||||
reg = (void *)&newregs.pc;
|
newregs.pc = reg;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
reg = (void *)&newregs.pstate;
|
newregs.pstate = reg;
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
reg = (void *)&newregs.orig_x0;
|
newregs.orig_x0 = reg;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reg = (void *)&newregs.regs[idx];
|
newregs.regs[idx] = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t));
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
goto out;
|
|
||||||
else
|
|
||||||
ubuf += sizeof(compat_ulong_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_user_regs(&newregs.user_regs))
|
if (valid_user_regs(&newregs.user_regs))
|
||||||
|
@ -714,7 +713,6 @@ static int compat_gpr_set(struct task_struct *target,
|
||||||
else
|
else
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue