forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/kernel/ptrace.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/kernel/ptrace.c
34 *
....@@ -30,6 +31,8 @@
3031 #include <linux/cn_proc.h>
3132 #include <linux/compat.h>
3233 #include <linux/sched/signal.h>
34
+
35
+#include <asm/syscall.h> /* for syscall_get_* */
3336
3437 /*
3538 * Access another process' address space via ptrace.
....@@ -115,6 +118,9 @@
115118 BUG_ON(!child->ptrace);
116119
117120 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
121
+#ifdef TIF_SYSCALL_EMU
122
+ clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
123
+#endif
118124
119125 child->parent = child->real_parent;
120126 list_del_init(&child->ptrace_entry);
....@@ -378,6 +384,26 @@
378384 return !err;
379385 }
380386
387
+static int check_ptrace_options(unsigned long data)
388
+{
389
+ if (data & ~(unsigned long)PTRACE_O_MASK)
390
+ return -EINVAL;
391
+
392
+ if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
393
+ if (!IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) ||
394
+ !IS_ENABLED(CONFIG_SECCOMP))
395
+ return -EINVAL;
396
+
397
+ if (!capable(CAP_SYS_ADMIN))
398
+ return -EPERM;
399
+
400
+ if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED ||
401
+ current->ptrace & PT_SUSPEND_SECCOMP)
402
+ return -EPERM;
403
+ }
404
+ return 0;
405
+}
406
+
381407 static int ptrace_attach(struct task_struct *task, long request,
382408 unsigned long addr,
383409 unsigned long flags)
....@@ -389,8 +415,16 @@
389415 if (seize) {
390416 if (addr != 0)
391417 goto out;
418
+ /*
419
+ * This duplicates the check in check_ptrace_options() because
420
+ * ptrace_attach() and ptrace_setoptions() have historically
421
+ * used different error codes for unknown ptrace options.
422
+ */
392423 if (flags & ~(unsigned long)PTRACE_O_MASK)
393424 goto out;
425
+ retval = check_ptrace_options(flags);
426
+ if (retval)
427
+ return retval;
394428 flags = PT_PTRACED | PT_SEIZED | (flags << PT_OPT_FLAG_SHIFT);
395429 } else {
396430 flags = PT_PTRACED;
....@@ -434,7 +468,7 @@
434468
435469 /* SEIZE doesn't trap tracee on attach */
436470 if (!seize)
437
- send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
471
+ send_sig_info(SIGSTOP, SEND_SIG_PRIV, task);
438472
439473 spin_lock(&task->sighand->siglock);
440474
....@@ -601,7 +635,7 @@
601635
602636 list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
603637 if (unlikely(p->ptrace & PT_EXITKILL))
604
- send_sig_info(SIGKILL, SEND_SIG_FORCED, p);
638
+ send_sig_info(SIGKILL, SEND_SIG_PRIV, p);
605639
606640 if (__ptrace_detach(tracer, p))
607641 list_add(&p->ptrace_entry, dead);
....@@ -663,22 +697,11 @@
663697 static int ptrace_setoptions(struct task_struct *child, unsigned long data)
664698 {
665699 unsigned flags;
700
+ int ret;
666701
667
- if (data & ~(unsigned long)PTRACE_O_MASK)
668
- return -EINVAL;
669
-
670
- if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
671
- if (!IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) ||
672
- !IS_ENABLED(CONFIG_SECCOMP))
673
- return -EINVAL;
674
-
675
- if (!capable(CAP_SYS_ADMIN))
676
- return -EPERM;
677
-
678
- if (seccomp_mode(&current->seccomp) != SECCOMP_MODE_DISABLED ||
679
- current->ptrace & PT_SUSPEND_SECCOMP)
680
- return -EPERM;
681
- }
702
+ ret = check_ptrace_options(data);
703
+ if (ret)
704
+ return ret;
682705
683706 /* Avoid intermediate state when all opts are cleared */
684707 flags = child->ptrace;
....@@ -689,7 +712,7 @@
689712 return 0;
690713 }
691714
692
-static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
715
+static int ptrace_getsiginfo(struct task_struct *child, kernel_siginfo_t *info)
693716 {
694717 unsigned long flags;
695718 int error = -ESRCH;
....@@ -705,7 +728,7 @@
705728 return error;
706729 }
707730
708
-static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
731
+static int ptrace_setsiginfo(struct task_struct *child, const kernel_siginfo_t *info)
709732 {
710733 unsigned long flags;
711734 int error = -ESRCH;
....@@ -751,7 +774,7 @@
751774 pending = &child->pending;
752775
753776 for (i = 0; i < arg.nr; ) {
754
- siginfo_t info;
777
+ kernel_siginfo_t info;
755778 unsigned long off = arg.off + i;
756779 bool found = false;
757780
....@@ -922,14 +945,107 @@
922945 * to ensure no machine forgets it.
923946 */
924947 EXPORT_SYMBOL_GPL(task_user_regset_view);
925
-#endif
948
+
949
+static unsigned long
950
+ptrace_get_syscall_info_entry(struct task_struct *child, struct pt_regs *regs,
951
+ struct ptrace_syscall_info *info)
952
+{
953
+ unsigned long args[ARRAY_SIZE(info->entry.args)];
954
+ int i;
955
+
956
+ info->op = PTRACE_SYSCALL_INFO_ENTRY;
957
+ info->entry.nr = syscall_get_nr(child, regs);
958
+ syscall_get_arguments(child, regs, args);
959
+ for (i = 0; i < ARRAY_SIZE(args); i++)
960
+ info->entry.args[i] = args[i];
961
+
962
+ /* args is the last field in struct ptrace_syscall_info.entry */
963
+ return offsetofend(struct ptrace_syscall_info, entry.args);
964
+}
965
+
966
+static unsigned long
967
+ptrace_get_syscall_info_seccomp(struct task_struct *child, struct pt_regs *regs,
968
+ struct ptrace_syscall_info *info)
969
+{
970
+ /*
971
+ * As struct ptrace_syscall_info.entry is currently a subset
972
+ * of struct ptrace_syscall_info.seccomp, it makes sense to
973
+ * initialize that subset using ptrace_get_syscall_info_entry().
974
+ * This can be reconsidered in the future if these structures
975
+ * diverge significantly enough.
976
+ */
977
+ ptrace_get_syscall_info_entry(child, regs, info);
978
+ info->op = PTRACE_SYSCALL_INFO_SECCOMP;
979
+ info->seccomp.ret_data = child->ptrace_message;
980
+
981
+ /* ret_data is the last field in struct ptrace_syscall_info.seccomp */
982
+ return offsetofend(struct ptrace_syscall_info, seccomp.ret_data);
983
+}
984
+
985
+static unsigned long
986
+ptrace_get_syscall_info_exit(struct task_struct *child, struct pt_regs *regs,
987
+ struct ptrace_syscall_info *info)
988
+{
989
+ info->op = PTRACE_SYSCALL_INFO_EXIT;
990
+ info->exit.rval = syscall_get_error(child, regs);
991
+ info->exit.is_error = !!info->exit.rval;
992
+ if (!info->exit.is_error)
993
+ info->exit.rval = syscall_get_return_value(child, regs);
994
+
995
+ /* is_error is the last field in struct ptrace_syscall_info.exit */
996
+ return offsetofend(struct ptrace_syscall_info, exit.is_error);
997
+}
998
+
999
+static int
1000
+ptrace_get_syscall_info(struct task_struct *child, unsigned long user_size,
1001
+ void __user *datavp)
1002
+{
1003
+ struct pt_regs *regs = task_pt_regs(child);
1004
+ struct ptrace_syscall_info info = {
1005
+ .op = PTRACE_SYSCALL_INFO_NONE,
1006
+ .arch = syscall_get_arch(child),
1007
+ .instruction_pointer = instruction_pointer(regs),
1008
+ .stack_pointer = user_stack_pointer(regs),
1009
+ };
1010
+ unsigned long actual_size = offsetof(struct ptrace_syscall_info, entry);
1011
+ unsigned long write_size;
1012
+
1013
+ /*
1014
+ * This does not need lock_task_sighand() to access
1015
+ * child->last_siginfo because ptrace_freeze_traced()
1016
+ * called earlier by ptrace_check_attach() ensures that
1017
+ * the tracee cannot go away and clear its last_siginfo.
1018
+ */
1019
+ switch (child->last_siginfo ? child->last_siginfo->si_code : 0) {
1020
+ case SIGTRAP | 0x80:
1021
+ switch (child->ptrace_message) {
1022
+ case PTRACE_EVENTMSG_SYSCALL_ENTRY:
1023
+ actual_size = ptrace_get_syscall_info_entry(child, regs,
1024
+ &info);
1025
+ break;
1026
+ case PTRACE_EVENTMSG_SYSCALL_EXIT:
1027
+ actual_size = ptrace_get_syscall_info_exit(child, regs,
1028
+ &info);
1029
+ break;
1030
+ }
1031
+ break;
1032
+ case SIGTRAP | (PTRACE_EVENT_SECCOMP << 8):
1033
+ actual_size = ptrace_get_syscall_info_seccomp(child, regs,
1034
+ &info);
1035
+ break;
1036
+ }
1037
+
1038
+ write_size = min(actual_size, user_size);
1039
+ return copy_to_user(datavp, &info, write_size) ? -EFAULT : actual_size;
1040
+}
1041
+#endif /* CONFIG_HAVE_ARCH_TRACEHOOK */
9261042
9271043 int ptrace_request(struct task_struct *child, long request,
9281044 unsigned long addr, unsigned long data)
9291045 {
9301046 bool seized = child->ptrace & PT_SEIZED;
9311047 int ret = -EIO;
932
- siginfo_t siginfo, *si;
1048
+ kernel_siginfo_t siginfo, *si;
9331049 void __user *datavp = (void __user *) data;
9341050 unsigned long __user *datalp = datavp;
9351051 unsigned long flags;
....@@ -963,9 +1079,8 @@
9631079 break;
9641080
9651081 case PTRACE_SETSIGINFO:
966
- if (copy_from_user(&siginfo, datavp, sizeof siginfo))
967
- ret = -EFAULT;
968
- else
1082
+ ret = copy_siginfo_from_user(&siginfo, datavp);
1083
+ if (!ret)
9691084 ret = ptrace_setsiginfo(child, &siginfo);
9701085 break;
9711086
....@@ -1118,9 +1233,8 @@
11181233 return ptrace_resume(child, request, data);
11191234
11201235 case PTRACE_KILL:
1121
- if (child->exit_state) /* already dead */
1122
- return 0;
1123
- return ptrace_resume(child, request, SIGKILL);
1236
+ send_sig_info(SIGKILL, SEND_SIG_NOINFO, child);
1237
+ return 0;
11241238
11251239 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
11261240 case PTRACE_GETREGSET:
....@@ -1128,7 +1242,7 @@
11281242 struct iovec kiov;
11291243 struct iovec __user *uiov = datavp;
11301244
1131
- if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
1245
+ if (!access_ok(uiov, sizeof(*uiov)))
11321246 return -EFAULT;
11331247
11341248 if (__get_user(kiov.iov_base, &uiov->iov_base) ||
....@@ -1140,6 +1254,10 @@
11401254 ret = __put_user(kiov.iov_len, &uiov->iov_len);
11411255 break;
11421256 }
1257
+
1258
+ case PTRACE_GET_SYSCALL_INFO:
1259
+ ret = ptrace_get_syscall_info(child, addr, datavp);
1260
+ break;
11431261 #endif
11441262
11451263 case PTRACE_SECCOMP_GET_FILTER:
....@@ -1235,7 +1353,7 @@
12351353 {
12361354 compat_ulong_t __user *datap = compat_ptr(data);
12371355 compat_ulong_t word;
1238
- siginfo_t siginfo;
1356
+ kernel_siginfo_t siginfo;
12391357 int ret;
12401358
12411359 switch (request) {
....@@ -1269,10 +1387,9 @@
12691387 break;
12701388
12711389 case PTRACE_SETSIGINFO:
1272
- if (copy_siginfo_from_user32(
1273
- &siginfo, (struct compat_siginfo __user *) datap))
1274
- ret = -EFAULT;
1275
- else
1390
+ ret = copy_siginfo_from_user32(
1391
+ &siginfo, (struct compat_siginfo __user *) datap);
1392
+ if (!ret)
12761393 ret = ptrace_setsiginfo(child, &siginfo);
12771394 break;
12781395 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
....@@ -1285,7 +1402,7 @@
12851402 compat_uptr_t ptr;
12861403 compat_size_t len;
12871404
1288
- if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
1405
+ if (!access_ok(uiov, sizeof(*uiov)))
12891406 return -EFAULT;
12901407
12911408 if (__get_user(ptr, &uiov->iov_base) ||