0001
0002 #include <linux/ptrace.h>
0003 #include <linux/sched.h>
0004 #include <linux/sched/task_stack.h>
0005 #include <linux/export.h>
0006 #include <asm/syscall.h>
0007
0008 static int collect_syscall(struct task_struct *target, struct syscall_info *info)
0009 {
0010 unsigned long args[6] = { };
0011 struct pt_regs *regs;
0012
0013 if (!try_get_task_stack(target)) {
0014
0015 memset(info, 0, sizeof(*info));
0016 info->data.nr = -1;
0017 return 0;
0018 }
0019
0020 regs = task_pt_regs(target);
0021 if (unlikely(!regs)) {
0022 put_task_stack(target);
0023 return -EAGAIN;
0024 }
0025
0026 info->sp = user_stack_pointer(regs);
0027 info->data.instruction_pointer = instruction_pointer(regs);
0028
0029 info->data.nr = syscall_get_nr(target, regs);
0030 if (info->data.nr != -1L)
0031 syscall_get_arguments(target, regs, args);
0032
0033 info->data.args[0] = args[0];
0034 info->data.args[1] = args[1];
0035 info->data.args[2] = args[2];
0036 info->data.args[3] = args[3];
0037 info->data.args[4] = args[4];
0038 info->data.args[5] = args[5];
0039
0040 put_task_stack(target);
0041 return 0;
0042 }
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 int task_current_syscall(struct task_struct *target, struct syscall_info *info)
0070 {
0071 unsigned long ncsw;
0072 unsigned int state;
0073
0074 if (target == current)
0075 return collect_syscall(target, info);
0076
0077 state = READ_ONCE(target->__state);
0078 if (unlikely(!state))
0079 return -EAGAIN;
0080
0081 ncsw = wait_task_inactive(target, state);
0082 if (unlikely(!ncsw) ||
0083 unlikely(collect_syscall(target, info)) ||
0084 unlikely(wait_task_inactive(target, state) != ncsw))
0085 return -EAGAIN;
0086
0087 return 0;
0088 }