summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/ptrace.c')
-rw-r--r--arch/arm64/kernel/ptrace.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index d882b833dbdb..2d4d67af1d38 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -37,6 +37,7 @@
#include <linux/regset.h>
#include <linux/tracehook.h>
#include <linux/elf.h>
+#include <linux/errno.h>
#include <asm/compat.h>
#include <asm/debug-monitors.h>
@@ -76,10 +77,10 @@ static void ptrace_hbptriggered(struct perf_event *bp,
.si_addr = (void __user *)(bkpt->trigger),
};
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_AARCH32_EL0
int i;
- if (!is_compat_task())
+ if (!is_a32_compat_task())
goto send_sig;
for (i = 0; i < ARM_MAX_BRP; ++i) {
@@ -653,6 +654,7 @@ static const struct user_regset_view user_aarch64_view = {
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
+#ifdef CONFIG_AARCH32_EL0
enum compat_regset {
REGSET_COMPAT_GPR,
@@ -829,9 +831,9 @@ static int compat_vfp_set(struct task_struct *target,
static const struct user_regset aarch32_regsets[] = {
[REGSET_COMPAT_GPR] = {
.core_note_type = NT_PRSTATUS,
- .n = COMPAT_ELF_NGREG,
- .size = sizeof(compat_elf_greg_t),
- .align = sizeof(compat_elf_greg_t),
+ .n = COMPAT_A32_ELF_NGREG,
+ .size = sizeof(compat_a32_elf_greg_t),
+ .align = sizeof(compat_a32_elf_greg_t),
.get = compat_gpr_get,
.set = compat_gpr_set
},
@@ -864,7 +866,7 @@ static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
tmp = tsk->mm->start_data;
else if (off == COMPAT_PT_TEXT_END_ADDR)
tmp = tsk->mm->end_code;
- else if (off < sizeof(compat_elf_gregset_t))
+ else if (off < sizeof(compat_a32_elf_gregset_t))
return copy_regset_to_user(tsk, &user_aarch32_view,
REGSET_COMPAT_GPR, off,
sizeof(compat_ulong_t), ret);
@@ -885,7 +887,7 @@ static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
if (off & 3 || off >= COMPAT_USER_SZ)
return -EIO;
- if (off >= sizeof(compat_elf_gregset_t))
+ if (off >= sizeof(compat_a32_elf_gregset_t))
return 0;
set_fs(KERNEL_DS);
@@ -1027,8 +1029,8 @@ static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
}
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
-long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
- compat_ulong_t caddr, compat_ulong_t cdata)
+long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
{
unsigned long addr = caddr;
unsigned long data = cdata;
@@ -1048,7 +1050,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
ret = copy_regset_to_user(child,
&user_aarch32_view,
REGSET_COMPAT_GPR,
- 0, sizeof(compat_elf_gregset_t),
+ 0, sizeof(compat_a32_elf_gregset_t),
datap);
break;
@@ -1056,7 +1058,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
ret = copy_regset_from_user(child,
&user_aarch32_view,
REGSET_COMPAT_GPR,
- 0, sizeof(compat_elf_gregset_t),
+ 0, sizeof(compat_a32_elf_gregset_t),
datap);
break;
@@ -1104,12 +1106,32 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
return ret;
}
-#endif /* CONFIG_COMPAT */
+#else /* !CONFIG_AARCH32_EL0 */
+long compat_a32_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
+{
+ return -EINVAL;
+}
+#endif /* !CONFIG_AARCH32_EL0 */
+
+/*
+ * In ILP32, compat_arch_ptrace is used via the compat syscall, we don't need
+ * to do anything special for ILP32 though; only for AARCH32.
+ */
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ compat_ulong_t caddr, compat_ulong_t cdata)
+{
+ if (is_a32_compat_task())
+ return compat_a32_arch_ptrace(child, request, caddr, cdata);
+ return compat_ptrace_request(child, request, caddr, cdata);
+}
+#endif
+
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
-#ifdef CONFIG_COMPAT
- if (is_compat_thread(task_thread_info(task)))
+#ifdef CONFIG_AARCH32_EL0
+ if (is_a32_compat_thread(task_thread_info(task)))
return &user_aarch32_view;
#endif
return &user_aarch64_view;
@@ -1136,7 +1158,7 @@ static void tracehook_report_syscall(struct pt_regs *regs,
* A scratch register (ip(r12) on AArch32, x7 on AArch64) is
* used to denote syscall entry/exit:
*/
- regno = (is_compat_task() ? 12 : 7);
+ regno = (is_a32_compat_task() ? 12 : 7);
saved_reg = regs->regs[regno];
regs->regs[regno] = dir;