Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <string.h>
3 : : #include "crtools.h"
4 : : #include "ptrace.h"
5 : : #include "parasite-syscall.h"
6 : :
7 : : struct syscall_exec_desc {
8 : : char *name;
9 : : unsigned nr;
10 : : };
11 : :
12 : : static struct syscall_exec_desc sc_exec_table[] = {
13 : : #define SYSCALL(__name, __nr) { .name = #__name, .nr = __nr, },
14 : : #include "sys-exec-tbl.c"
15 : : #undef SYSCALL
16 : : { }, /* terminator */
17 : : };
18 : :
19 : 0 : static struct syscall_exec_desc *find_syscall(char *name)
20 : : {
21 : : int i;
22 : :
23 [ # # ]: 0 : for (i = 0; sc_exec_table[i].name != NULL; i++)
24 [ # # ]: 0 : if (!strcmp(sc_exec_table[i].name, name))
25 : 0 : return &sc_exec_table[i];
26 : :
27 : : return NULL;
28 : : }
29 : :
30 : : #define MAX_ARGS 6
31 : :
32 : 0 : static int execute_syscall(struct parasite_ctl *ctl,
33 : : struct syscall_exec_desc *scd, char **opt)
34 : : {
35 : : int i, err;
36 : 0 : unsigned long args[MAX_ARGS] = {}, ret, r_mem_size = 0;
37 : 0 : void *r_mem = NULL;
38 : :
39 [ # # ]: 0 : for (i = 0; i < MAX_ARGS; i++) {
40 [ # # ]: 0 : if (opt[i] == NULL)
41 : : break;
42 : :
43 [ # # ]: 0 : if (opt[i][0] == '&') {
44 : : int len;
45 : :
46 [ # # ]: 0 : if (!r_mem) {
47 : 0 : err = parasite_map_exchange(ctl, PAGE_SIZE);
48 [ # # ]: 0 : if (err)
49 : : return err;
50 : :
51 : 0 : r_mem_size = PAGE_SIZE;
52 : 0 : r_mem = ctl->local_map;
53 : : }
54 : :
55 : 0 : len = strlen(opt[i]);
56 [ # # ]: 0 : if (r_mem_size < len) {
57 : 0 : pr_err("Arg size overflow\n");
58 : : return -1;
59 : : }
60 : :
61 : 0 : memcpy(r_mem, opt[i] + 1, len);
62 : 0 : args[i] = (unsigned long)ctl->remote_map + (r_mem - ctl->local_map);
63 : 0 : pr_info("Pushing mem arg [%s]\n", (char *)r_mem);
64 : 0 : r_mem_size -= len;
65 : 0 : r_mem += len;
66 : : } else
67 : 0 : args[i] = strtol(opt[i], NULL, 0);
68 : : }
69 : :
70 : 0 : pr_info("Calling %d with %lu %lu %lu %lu %lu %lu\n", scd->nr,
71 : : args[0], args[1], args[2], args[3], args[4], args[5]);
72 : :
73 : 0 : err = syscall_seized(ctl, scd->nr, &ret,
74 : : args[0], args[1], args[2], args[3], args[4], args[5]);
75 [ # # ]: 0 : if (err)
76 : : return err;
77 : :
78 : 0 : pr_msg("Syscall returned %lx(%d)\n", ret, (int)ret);
79 : : return 0;
80 : : }
81 : :
82 : 0 : int cr_exec(int pid, char **opt)
83 : : {
84 : 0 : char *sys_name = opt[0];
85 : : struct syscall_exec_desc *si;
86 : : struct parasite_ctl *ctl;
87 : 0 : LIST_HEAD(vma_area_list);
88 : 0 : int ret = -1, prev_state;
89 : :
90 [ # # ]: 0 : if (!sys_name) {
91 : 0 : pr_err("Syscall name required\n");
92 : 0 : goto out;
93 : : }
94 : :
95 : 0 : si = find_syscall(sys_name);
96 [ # # ]: 0 : if (!si) {
97 : 0 : pr_err("Unknown syscall [%s]\n", sys_name);
98 : 0 : goto out;
99 : : }
100 : :
101 : 0 : prev_state = ret = seize_task(pid, -1, NULL, NULL);
102 [ # # ]: 0 : if (ret < 0) {
103 : 0 : pr_err("Can't seize task %d\n", pid);
104 : 0 : goto out;
105 : : }
106 : :
107 : 0 : ret = collect_mappings(pid, &vma_area_list);
108 [ # # ]: 0 : if (ret) {
109 : 0 : pr_err("Can't collect vmas for %d\n", pid);
110 : 0 : goto out_unseize;
111 : : }
112 : :
113 : 0 : ctl = parasite_prep_ctl(pid, &vma_area_list);
114 [ # # ]: 0 : if (!ctl) {
115 : 0 : pr_err("Can't prep ctl %d\n", pid);
116 : 0 : goto out_unseize;
117 : : }
118 : :
119 : 0 : ret = execute_syscall(ctl, si, opt + 1);
120 [ # # ]: 0 : if (ret < 0)
121 : 0 : pr_err("Can't execure syscall remotely\n");
122 : :
123 : 0 : parasite_cure_seized(ctl, NULL);
124 : : out_unseize:
125 : 0 : unseize_task(pid, prev_state);
126 : : out:
127 : 0 : return ret;
128 : 0 : }
|