1#include <linux/ptrace.h>
2#include <linux/sched.h>
3#include <linux/module.h>
4#include <asm/syscall.h>
5
6static int collect_syscall(struct task_struct *target, long *callno,
7 unsigned long args[6], unsigned int maxargs,
8 unsigned long *sp, unsigned long *pc)
9{
10 struct pt_regs *regs = task_pt_regs(target);
11 if (unlikely(!regs))
12 return -EAGAIN;
13
14 *sp = user_stack_pointer(regs);
15 *pc = instruction_pointer(regs);
16
17 *callno = syscall_get_nr(target, regs);
18 if (*callno != -1L && maxargs > 0)
19 syscall_get_arguments(target, regs, 0, maxargs, args);
20
21 return 0;
22}
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50int task_current_syscall(struct task_struct *target, long *callno,
51 unsigned long args[6], unsigned int maxargs,
52 unsigned long *sp, unsigned long *pc)
53{
54 long state;
55 unsigned long ncsw;
56
57 if (unlikely(maxargs > 6))
58 return -EINVAL;
59
60 if (target == current)
61 return collect_syscall(target, callno, args, maxargs, sp, pc);
62
63 state = target->state;
64 if (unlikely(!state))
65 return -EAGAIN;
66
67 ncsw = wait_task_inactive(target, state);
68 if (unlikely(!ncsw) ||
69 unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
70 unlikely(wait_task_inactive(target, state) != ncsw))
71 return -EAGAIN;
72
73 return 0;
74}
75EXPORT_SYMBOL_GPL(task_current_syscall);
76