diff options
Diffstat (limited to 'arch/arm64/kernel/ptrace.c')
-rw-r--r-- | arch/arm64/kernel/ptrace.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 8a4ae8e73213..d882b833dbdb 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/smp.h> | 27 | #include <linux/smp.h> |
28 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
29 | #include <linux/user.h> | 29 | #include <linux/user.h> |
30 | #include <linux/seccomp.h> | ||
30 | #include <linux/security.h> | 31 | #include <linux/security.h> |
31 | #include <linux/init.h> | 32 | #include <linux/init.h> |
32 | #include <linux/signal.h> | 33 | #include <linux/signal.h> |
@@ -551,6 +552,32 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset, | |||
551 | return ret; | 552 | return ret; |
552 | } | 553 | } |
553 | 554 | ||
555 | static int system_call_get(struct task_struct *target, | ||
556 | const struct user_regset *regset, | ||
557 | unsigned int pos, unsigned int count, | ||
558 | void *kbuf, void __user *ubuf) | ||
559 | { | ||
560 | int syscallno = task_pt_regs(target)->syscallno; | ||
561 | |||
562 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
563 | &syscallno, 0, -1); | ||
564 | } | ||
565 | |||
566 | static int system_call_set(struct task_struct *target, | ||
567 | const struct user_regset *regset, | ||
568 | unsigned int pos, unsigned int count, | ||
569 | const void *kbuf, const void __user *ubuf) | ||
570 | { | ||
571 | int syscallno, ret; | ||
572 | |||
573 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1); | ||
574 | if (ret) | ||
575 | return ret; | ||
576 | |||
577 | task_pt_regs(target)->syscallno = syscallno; | ||
578 | return ret; | ||
579 | } | ||
580 | |||
554 | enum aarch64_regset { | 581 | enum aarch64_regset { |
555 | REGSET_GPR, | 582 | REGSET_GPR, |
556 | REGSET_FPR, | 583 | REGSET_FPR, |
@@ -559,6 +586,7 @@ enum aarch64_regset { | |||
559 | REGSET_HW_BREAK, | 586 | REGSET_HW_BREAK, |
560 | REGSET_HW_WATCH, | 587 | REGSET_HW_WATCH, |
561 | #endif | 588 | #endif |
589 | REGSET_SYSTEM_CALL, | ||
562 | }; | 590 | }; |
563 | 591 | ||
564 | static const struct user_regset aarch64_regsets[] = { | 592 | static const struct user_regset aarch64_regsets[] = { |
@@ -608,6 +636,14 @@ static const struct user_regset aarch64_regsets[] = { | |||
608 | .set = hw_break_set, | 636 | .set = hw_break_set, |
609 | }, | 637 | }, |
610 | #endif | 638 | #endif |
639 | [REGSET_SYSTEM_CALL] = { | ||
640 | .core_note_type = NT_ARM_SYSTEM_CALL, | ||
641 | .n = 1, | ||
642 | .size = sizeof(int), | ||
643 | .align = sizeof(int), | ||
644 | .get = system_call_get, | ||
645 | .set = system_call_set, | ||
646 | }, | ||
611 | }; | 647 | }; |
612 | 648 | ||
613 | static const struct user_regset_view user_aarch64_view = { | 649 | static const struct user_regset_view user_aarch64_view = { |
@@ -1114,6 +1150,10 @@ static void tracehook_report_syscall(struct pt_regs *regs, | |||
1114 | 1150 | ||
1115 | asmlinkage int syscall_trace_enter(struct pt_regs *regs) | 1151 | asmlinkage int syscall_trace_enter(struct pt_regs *regs) |
1116 | { | 1152 | { |
1153 | /* Do the secure computing check first; failures should be fast. */ | ||
1154 | if (secure_computing() == -1) | ||
1155 | return -1; | ||
1156 | |||
1117 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1157 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1118 | tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); | 1158 | tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); |
1119 | 1159 | ||