Skip to content

Commit 1e56f6d

Browse files
author
Al Viro
committed
Merge branches 'regset.x86', 'regset.ia64', 'regset.sparc' and 'regset.arm64' into work.regset
5 parents b4e9c95 + 4dfa103 + e3fdfa3 + b7e46c5 + d547175 commit 1e56f6d

File tree

7 files changed

+588
-410
lines changed

7 files changed

+588
-410
lines changed

arch/arm64/kernel/ptrace.c

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,22 @@ enum compat_regset {
12371237
REGSET_COMPAT_VFP,
12381238
};
12391239

1240+
static inline compat_ulong_t compat_get_user_reg(struct task_struct *task, int idx)
1241+
{
1242+
struct pt_regs *regs = task_pt_regs(task);
1243+
1244+
switch (idx) {
1245+
case 15:
1246+
return regs->pc;
1247+
case 16:
1248+
return pstate_to_compat_psr(regs->pstate);
1249+
case 17:
1250+
return regs->orig_x0;
1251+
default:
1252+
return regs->regs[idx];
1253+
}
1254+
}
1255+
12401256
static int compat_gpr_get(struct task_struct *target,
12411257
const struct user_regset *regset,
12421258
unsigned int pos, unsigned int count,
@@ -1255,23 +1271,7 @@ static int compat_gpr_get(struct task_struct *target,
12551271
return -EIO;
12561272

12571273
for (i = 0; i < num_regs; ++i) {
1258-
unsigned int idx = start + i;
1259-
compat_ulong_t reg;
1260-
1261-
switch (idx) {
1262-
case 15:
1263-
reg = task_pt_regs(target)->pc;
1264-
break;
1265-
case 16:
1266-
reg = task_pt_regs(target)->pstate;
1267-
reg = pstate_to_compat_psr(reg);
1268-
break;
1269-
case 17:
1270-
reg = task_pt_regs(target)->orig_x0;
1271-
break;
1272-
default:
1273-
reg = task_pt_regs(target)->regs[idx];
1274-
}
1274+
compat_ulong_t reg = compat_get_user_reg(target, start + i);
12751275

12761276
if (kbuf) {
12771277
memcpy(kbuf, &reg, sizeof(reg));
@@ -1541,9 +1541,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
15411541
else if (off == COMPAT_PT_TEXT_END_ADDR)
15421542
tmp = tsk->mm->end_code;
15431543
else if (off < sizeof(compat_elf_gregset_t))
1544-
return copy_regset_to_user(tsk, &user_aarch32_view,
1545-
REGSET_COMPAT_GPR, off,
1546-
sizeof(compat_ulong_t), ret);
1544+
tmp = compat_get_user_reg(tsk, off >> 2);
15471545
else if (off >= COMPAT_USER_SZ)
15481546
return -EIO;
15491547
else
@@ -1555,23 +1553,34 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
15551553
static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
15561554
compat_ulong_t val)
15571555
{
1558-
int ret;
1559-
mm_segment_t old_fs = get_fs();
1556+
struct pt_regs newregs = *task_pt_regs(tsk);
1557+
unsigned int idx = off / 4;
15601558

15611559
if (off & 3 || off >= COMPAT_USER_SZ)
15621560
return -EIO;
15631561

15641562
if (off >= sizeof(compat_elf_gregset_t))
15651563
return 0;
15661564

1567-
set_fs(KERNEL_DS);
1568-
ret = copy_regset_from_user(tsk, &user_aarch32_view,
1569-
REGSET_COMPAT_GPR, off,
1570-
sizeof(compat_ulong_t),
1571-
&val);
1572-
set_fs(old_fs);
1565+
switch (idx) {
1566+
case 15:
1567+
newregs.pc = val;
1568+
break;
1569+
case 16:
1570+
newregs.pstate = compat_psr_to_pstate(val);
1571+
break;
1572+
case 17:
1573+
newregs.orig_x0 = val;
1574+
break;
1575+
default:
1576+
newregs.regs[idx] = val;
1577+
}
1578+
1579+
if (!valid_user_regs(&newregs.user_regs, tsk))
1580+
return -EINVAL;
15731581

1574-
return ret;
1582+
*task_pt_regs(tsk) = newregs;
1583+
return 0;
15751584
}
15761585

15771586
#ifdef CONFIG_HAVE_HW_BREAKPOINT

0 commit comments

Comments
 (0)