Branch data Line data Source code
1 : : #include <stdlib.h>
2 : : #include <stdio.h>
3 : : #include <stdarg.h>
4 : : #include <string.h>
5 : : #include <errno.h>
6 : : #include <unistd.h>
7 : : #include <stdbool.h>
8 : : #include <limits.h>
9 : : #include <signal.h>
10 : :
11 : : #include <sys/types.h>
12 : : #include <sys/time.h>
13 : : #include <sys/resource.h>
14 : : #include <sys/wait.h>
15 : :
16 : : #include "compiler.h"
17 : : #include "asm/types.h"
18 : : #include "util.h"
19 : : #include "ptrace.h"
20 : : #include "proc_parse.h"
21 : :
22 : 3676 : int unseize_task(pid_t pid, int orig_st, int st)
23 : : {
24 : 3676 : pr_debug("\tUnseizing %d into %d\n", pid, st);
25 : :
26 [ + + ]: 3676 : if (st == TASK_DEAD)
27 : 919 : kill(pid, SIGKILL);
28 [ - + ]: 2757 : else if (st == TASK_STOPPED) {
29 [ # # ]: 0 : if (orig_st == TASK_ALIVE)
30 : 0 : kill(pid, SIGSTOP);
31 [ - + ]: 2757 : } else if (st == TASK_ALIVE)
32 : : /* do nothing */ ;
33 : : else
34 : 0 : pr_err("Unknown final state %d\n", st);
35 : :
36 : 3676 : return ptrace(PTRACE_DETACH, pid, NULL, NULL);
37 : : }
38 : :
39 : : /*
40 : : * This routine seizes task putting it into a special
41 : : * state where we can manipulate the task via ptrace
42 : : * interface, and finally we can detach ptrace out of
43 : : * of it so the task would not know if it was saddled
44 : : * up with someone else.
45 : : */
46 : :
47 : 5657 : int seize_task(pid_t pid, pid_t ppid, pid_t *pgid, pid_t *sid)
48 : : {
49 : : siginfo_t si;
50 : : int status;
51 : : int ret, ret2, ptrace_errno;
52 : : struct proc_pid_stat_small ps;
53 : :
54 : 5657 : ret = ptrace(PTRACE_SEIZE, pid, NULL, 0);
55 : 5657 : ptrace_errno = errno;
56 [ + + ]: 5657 : if (ret == 0) {
57 : : /*
58 : : * If we SEIZE-d the task stop it before going
59 : : * and reading its stat from proc. Otherwise task
60 : : * may die _while_ we're doing it and we'll have
61 : : * inconsistent seize/state pair.
62 : : *
63 : : * If task dies after we seize it but before we
64 : : * do this interrupt, we'll notice it via proc.
65 : : */
66 : 5558 : ret = ptrace(PTRACE_INTERRUPT, pid, NULL, NULL);
67 [ - + ]: 5558 : if (ret < 0) {
68 : 0 : pr_perror("SEIZE %d: can't interrupt task", pid);
69 : 0 : ptrace(PTRACE_DETACH, pid, NULL, NULL);
70 : 0 : goto err;
71 : : }
72 : : }
73 : :
74 : : /*
75 : : * It's ugly, but the ptrace API doesn't allow to distinguish
76 : : * attaching to zombie from other errors. Thus we have to parse
77 : : * the target's /proc/pid/stat. Sad, but parse whatever else
78 : : * we might nead at that early point.
79 : : */
80 : :
81 : 5657 : ret2 = parse_pid_stat_small(pid, &ps);
82 [ + + ]: 5657 : if (ret2 < 0)
83 : : return -1;
84 : :
85 [ + + ]: 5646 : if (pgid)
86 : 3764 : *pgid = ps.pgid;
87 [ + + ]: 5646 : if (sid)
88 : 3764 : *sid = ps.sid;
89 : :
90 [ + + ]: 5646 : if (ret < 0) {
91 [ - + ]: 88 : if (ps.state != 'Z') {
92 [ # # ]: 0 : if (pid == getpid())
93 : 0 : pr_err("The criu itself is within dumped tree.\n");
94 : : else
95 : 0 : pr_err("Unseizable non-zombie %d found, state %c, err %d/%d\n",
96 : : pid, ps.state, ret, ptrace_errno);
97 : : return -1;
98 : : }
99 : :
100 : : return TASK_DEAD;
101 : : }
102 : :
103 [ + + ][ - + ]: 5558 : if ((ppid != -1) && (ps.ppid != ppid)) {
104 : 0 : pr_err("Task pid reused while suspending (%d: %d -> %d)\n",
105 : : pid, ppid, ps.ppid);
106 : 5558 : goto err;
107 : : }
108 : :
109 : : try_again:
110 : 5558 : ret = wait4(pid, &status, __WALL, NULL);
111 [ - + ]: 5558 : if (ret < 0) {
112 : 0 : pr_perror("SEIZE %d: can't wait task", pid);
113 : 0 : goto err;
114 : : }
115 : :
116 [ - + ]: 5558 : if (ret != pid) {
117 : 0 : pr_err("SEIZE %d: wrong task attached (%d)\n", pid, ret);
118 : 0 : goto err;
119 : : }
120 : :
121 [ - + ]: 5558 : if (!WIFSTOPPED(status)) {
122 : 0 : pr_err("SEIZE %d: task not stopped after seize\n", pid);
123 : 0 : goto err;
124 : : }
125 : :
126 : 5558 : ret = ptrace(PTRACE_GETSIGINFO, pid, NULL, &si);
127 [ - + ]: 5558 : if (ret < 0) {
128 : 0 : pr_perror("SEIZE %d: can't read signfo", pid);
129 : 0 : goto err;
130 : : }
131 : :
132 [ - + ]: 5558 : if (SI_EVENT(si.si_code) != PTRACE_EVENT_STOP) {
133 : : /*
134 : : * Kernel notifies us about the task being seized received some
135 : : * event other than the STOP, i.e. -- a signal. Let the task
136 : : * handle one and repeat.
137 : : */
138 : :
139 [ # # ]: 0 : if (ptrace(PTRACE_CONT, pid, NULL,
140 : 0 : (void *)(unsigned long)si.si_signo)) {
141 : 0 : pr_perror("Can't continue signal handling, aborting");
142 : 0 : goto err;
143 : : }
144 : :
145 : : goto try_again;
146 : : }
147 : :
148 [ + + ]: 5558 : if (si.si_signo == SIGTRAP)
149 : : return TASK_ALIVE;
150 [ + - ]: 16 : else if (si.si_signo == SIGSTOP) {
151 : : /*
152 : : * PTRACE_SEIZE doesn't affect signal or group stop state.
153 : : * Currently ptrace reported that task is in stopped state.
154 : : * We need to start task again, and it will be trapped
155 : : * immediately, because we sent PTRACE_INTERRUPT to it.
156 : : */
157 : 16 : ret = ptrace(PTRACE_CONT, pid, 0, 0);
158 [ - + ]: 16 : if (ret) {
159 : 0 : pr_perror("Unable to start process");
160 : 0 : goto err_stop;
161 : : }
162 : :
163 : 16 : ret = wait4(pid, &status, __WALL, NULL);
164 [ - + ]: 16 : if (ret < 0) {
165 : 0 : pr_perror("SEIZE %d: can't wait task", pid);
166 : 0 : goto err_stop;
167 : : }
168 : :
169 [ - + ]: 16 : if (ret != pid) {
170 : 0 : pr_err("SEIZE %d: wrong task attached (%d)\n", pid, ret);
171 : 0 : goto err_stop;
172 : : }
173 : :
174 [ - + ]: 16 : if (!WIFSTOPPED(status)) {
175 : 0 : pr_err("SEIZE %d: task not stopped after seize\n", pid);
176 : 0 : goto err_stop;
177 : : }
178 : :
179 : : return TASK_STOPPED;
180 : : } else {
181 : 0 : pr_err("SEIZE %d: unsupported stop signal %d\n", pid, si.si_signo);
182 : 0 : goto err;
183 : : }
184 : :
185 : : err_stop:
186 : 0 : kill(pid, SIGSTOP);
187 : : err:
188 : 0 : ptrace(PTRACE_DETACH, pid, NULL, NULL);
189 : 0 : return -1;
190 : : }
191 : :
192 : 3664 : int ptrace_peek_area(pid_t pid, void *dst, void *addr, long bytes)
193 : : {
194 : : unsigned long w;
195 [ + - ]: 3664 : if (bytes & (sizeof(long) - 1))
196 : : return -1;
197 [ + + ]: 7328 : for (w = 0; w < bytes / sizeof(long); w++) {
198 : : unsigned long *d = dst, *a = addr;
199 : 3664 : d[w] = ptrace(PTRACE_PEEKDATA, pid, a + w, NULL);
200 [ - + ][ # # ]: 3664 : if (d[w] == -1U && errno)
201 : : goto err;
202 : : }
203 : : return 0;
204 : : err:
205 : : return -2;
206 : : }
207 : :
208 : 7328 : int ptrace_poke_area(pid_t pid, void *src, void *addr, long bytes)
209 : : {
210 : : unsigned long w;
211 [ + - ]: 7328 : if (bytes & (sizeof(long) - 1))
212 : : return -1;
213 [ + + ]: 14656 : for (w = 0; w < bytes / sizeof(long); w++) {
214 : : unsigned long *s = src, *a = addr;
215 [ + - ]: 7328 : if (ptrace(PTRACE_POKEDATA, pid, a + w, s[w]))
216 : : goto err;
217 : : }
218 : : return 0;
219 : : err:
220 : : return -2;
221 : : }
222 : :
223 : : /* don't swap big space, it might overflow the stack */
224 : 3664 : int ptrace_swap_area(pid_t pid, void *dst, void *src, long bytes)
225 : : {
226 : 3664 : void *t = alloca(bytes);
227 : :
228 [ + - ]: 3664 : if (ptrace_peek_area(pid, t, dst, bytes))
229 : : return -1;
230 : :
231 [ - + ]: 3664 : if (ptrace_poke_area(pid, src, dst, bytes)) {
232 [ # # ]: 0 : if (ptrace_poke_area(pid, t, dst, bytes))
233 : : return -2;
234 : 0 : return -1;
235 : : }
236 : :
237 : : memcpy(src, t, bytes);
238 : :
239 : 3664 : return 0;
240 : : }
|