Branch data Line data Source code
1 : : #include <sys/time.h>
2 : : #include <stdio.h>
3 : : #include <stdlib.h>
4 : : #include <stdarg.h>
5 : : #include <signal.h>
6 : : #include <limits.h>
7 : : #include <unistd.h>
8 : : #include <errno.h>
9 : : #include <string.h>
10 : : #include <parasite.h>
11 : :
12 : : #include <fcntl.h>
13 : :
14 : : #include <sys/types.h>
15 : : #include <sys/stat.h>
16 : : #include <sys/vfs.h>
17 : :
18 : : #include <sys/sendfile.h>
19 : : #include <sys/mman.h>
20 : :
21 : : #include <sched.h>
22 : : #include <sys/resource.h>
23 : :
24 : : #include <linux/major.h>
25 : : #include <linux/capability.h>
26 : :
27 : : #include "protobuf.h"
28 : : #include "protobuf/fdinfo.pb-c.h"
29 : : #include "protobuf/fs.pb-c.h"
30 : : #include "protobuf/mm.pb-c.h"
31 : : #include "protobuf/creds.pb-c.h"
32 : : #include "protobuf/core.pb-c.h"
33 : :
34 : : #include "types.h"
35 : : #include "list.h"
36 : : #include "file-ids.h"
37 : : #include "kcmp-ids.h"
38 : : #include "compiler.h"
39 : : #include "crtools.h"
40 : : #include "syscall.h"
41 : : #include "ptrace.h"
42 : : #include "util.h"
43 : : #include "sockets.h"
44 : : #include "namespaces.h"
45 : : #include "image.h"
46 : : #include "proc_parse.h"
47 : : #include "parasite.h"
48 : : #include "parasite-syscall.h"
49 : : #include "files.h"
50 : : #include "files-reg.h"
51 : : #include "pipes.h"
52 : : #include "fifo.h"
53 : : #include "shmem.h"
54 : : #include "sk-inet.h"
55 : : #include "eventfd.h"
56 : : #include "eventpoll.h"
57 : : #include "inotify.h"
58 : : #include "signalfd.h"
59 : : #include "pstree.h"
60 : : #include "mount.h"
61 : : #include "tty.h"
62 : : #include "net.h"
63 : : #include "sk-packet.h"
64 : : #include "cpu.h"
65 : : #include "fpu.h"
66 : : #include "elf.h"
67 : :
68 : : #ifndef CONFIG_X86_64
69 : : # error No x86-32 support yet
70 : : #endif
71 : :
72 : : static char loc_buf[PAGE_SIZE];
73 : : static int pidns_proc = -1;
74 : :
75 : 1047 : void free_mappings(struct list_head *vma_area_list)
76 : : {
77 : : struct vma_area *vma_area, *p;
78 : :
79 [ + + ]: 33147 : list_for_each_entry_safe(vma_area, p, vma_area_list, list) {
80 [ + + ]: 32100 : if (vma_area->vm_file_fd > 0)
81 : 3326 : close(vma_area->vm_file_fd);
82 : 32100 : free(vma_area);
83 : : }
84 : :
85 : : INIT_LIST_HEAD(vma_area_list);
86 : 1047 : }
87 : :
88 : 349 : int collect_mappings(pid_t pid, struct list_head *vma_area_list)
89 : : {
90 : 349 : int ret = -1;
91 : :
92 : 349 : pr_info("\n");
93 : 349 : pr_info("Collecting mappings (pid: %d)\n", pid);
94 : 349 : pr_info("----------------------------------------\n");
95 : :
96 : 349 : ret = parse_smaps(pid, vma_area_list, true);
97 [ + - ]: 349 : if (ret < 0)
98 : : goto err;
99 : :
100 [ + + ]: 6404 : pr_info_vma_list(vma_area_list);
101 : :
102 : 349 : pr_info("----------------------------------------\n");
103 : 349 : ret = 0;
104 : :
105 : : err:
106 : 349 : return ret;
107 : : }
108 : :
109 : 381 : static int dump_sched_info(int pid, ThreadCoreEntry *tc)
110 : : {
111 : : int ret;
112 : : struct sched_param sp;
113 : :
114 : : BUILD_BUG_ON(SCHED_OTHER != 0); /* default in proto message */
115 : :
116 : 381 : ret = sched_getscheduler(pid);
117 [ - + ]: 381 : if (ret < 0) {
118 : 0 : pr_perror("Can't get sched policy for %d", pid);
119 : : return -1;
120 : : }
121 : :
122 : 381 : pr_info("%d has %d sched policy\n", pid, ret);
123 : 381 : tc->has_sched_policy = true;
124 : 381 : tc->sched_policy = ret;
125 : :
126 [ + + ]: 381 : if ((ret == SCHED_RR) || (ret == SCHED_FIFO)) {
127 : 2 : ret = sched_getparam(pid, &sp);
128 [ - + ]: 2 : if (ret < 0) {
129 : 0 : pr_perror("Can't get sched param for %d", pid);
130 : : return -1;
131 : : }
132 : :
133 : 2 : pr_info("\tdumping %d prio for %d\n", sp.sched_priority, pid);
134 : 2 : tc->has_sched_prio = true;
135 : 2 : tc->sched_prio = sp.sched_priority;
136 : : }
137 : :
138 : : /*
139 : : * The nice is ignored for RT sched policies, but is stored
140 : : * in kernel. Thus we have to take it with us in the image.
141 : : */
142 : :
143 : 381 : errno = 0;
144 : 381 : ret = getpriority(PRIO_PROCESS, pid);
145 [ - + ]: 381 : if (errno) {
146 : 0 : pr_perror("Can't get nice for %d", pid);
147 : : return -1;
148 : : }
149 : :
150 : 381 : pr_info("\tdumping %d nice for %d\n", ret, pid);
151 : 381 : tc->has_sched_nice = true;
152 : 381 : tc->sched_nice = ret;
153 : :
154 : : return 0;
155 : : }
156 : :
157 : : struct cr_fdset *glob_fdset;
158 : :
159 : 349 : static int collect_fds(pid_t pid, struct parasite_drain_fd *dfds)
160 : : {
161 : : struct dirent *de;
162 : : DIR *fd_dir;
163 : : int n;
164 : :
165 : 349 : pr_info("\n");
166 : 349 : pr_info("Collecting fds (pid: %d)\n", pid);
167 : 349 : pr_info("----------------------------------------\n");
168 : :
169 [ + - ][ - + ]: 349 : fd_dir = opendir_proc(pid, "fd");
[ - + ]
170 [ + - ]: 349 : if (!fd_dir)
171 : : return -1;
172 : :
173 : : n = 0;
174 [ + + ]: 2552 : while ((de = readdir(fd_dir))) {
175 [ + + ]: 2203 : if (dir_dots(de))
176 : 698 : continue;
177 : :
178 [ + - ]: 1505 : if (n > PARASITE_MAX_FDS - 1)
179 : : return -ENOMEM;
180 : :
181 : 2203 : dfds->fds[n++] = atoi(de->d_name);
182 : : }
183 : :
184 : 349 : dfds->nr_fds = n;
185 : 349 : pr_info("Found %d file descriptors\n", n);
186 : 349 : pr_info("----------------------------------------\n");
187 : :
188 : 349 : closedir(fd_dir);
189 : :
190 : 349 : return 0;
191 : : }
192 : :
193 : : static u32 make_gen_id(const struct fd_parms *p)
194 : : {
195 : 1505 : return ((u32)p->stat.st_dev) ^ ((u32)p->stat.st_ino) ^ ((u32)p->pos);
196 : : }
197 : :
198 : 1505 : int do_dump_gen_file(struct fd_parms *p, int lfd,
199 : : const struct fdtype_ops *ops, const struct cr_fdset *cr_fdset)
200 : : {
201 : 1505 : FdinfoEntry e = FDINFO_ENTRY__INIT;
202 : 1505 : int ret = -1;
203 : :
204 : 1505 : e.type = ops->type;
205 : 1505 : e.id = make_gen_id(p);
206 : 1505 : e.fd = p->fd;
207 : 1505 : e.flags = p->fd_flags;
208 : :
209 : 1505 : ret = fd_id_generate(p->pid, &e);
210 [ + + ]: 1505 : if (ret == 1) /* new ID generated */
211 : 820 : ret = ops->dump(lfd, e.id, p);
212 : :
213 [ + - ]: 1505 : if (ret < 0)
214 : : return -1;
215 : :
216 : 1505 : pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8lx fd: %d\n",
217 : : ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
218 : :
219 : 1505 : return pb_write_one(fdset_fd(cr_fdset, CR_FD_FDINFO), &e, PB_FDINFO);
220 : : }
221 : :
222 : 349 : static int dump_task_exe_link(pid_t pid, MmEntry *mm)
223 : : {
224 : 349 : struct fd_parms params = FD_PARMS_INIT;
225 : : int fd, ret;
226 : :
227 [ - + ]: 349 : fd = open_proc(pid, "exe");
228 [ + - ]: 349 : if (fd < 0)
229 : : return -1;
230 : :
231 [ - + ]: 349 : if (fstat(fd, ¶ms.stat) < 0) {
232 : 0 : pr_perror("Can't fstat exe link");
233 : : return -1;
234 : : }
235 : :
236 : 349 : mm->exe_file_id = fd_id_generate_special();
237 : :
238 : 349 : ret = dump_one_reg_file(fd, mm->exe_file_id, ¶ms);
239 : 349 : close(fd);
240 : :
241 : : return ret;
242 : : }
243 : :
244 : 1505 : static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
245 : : struct fd_opts *opts, struct fd_parms *p)
246 : : {
247 [ - + ]: 1505 : if (fstat(lfd, &p->stat) < 0) {
248 : 0 : pr_perror("Can't stat fd %d\n", lfd);
249 : 0 : return -1;
250 : : }
251 : :
252 : 1505 : p->ctl = ctl;
253 : 1505 : p->fd = fd;
254 : 1505 : p->pos = lseek(lfd, 0, SEEK_CUR);
255 : 1505 : p->flags = fcntl(lfd, F_GETFL);
256 : 1505 : p->pid = ctl->pid;
257 : 1505 : p->fd_flags = opts->flags;
258 : :
259 : 1505 : fown_entry__init(&p->fown);
260 : :
261 : 1505 : pr_info("%d fdinfo %d: pos: 0x%16lx flags: %16o/%#x\n",
262 : : ctl->pid, fd, p->pos, p->flags, (int)p->fd_flags);
263 : :
264 : 1505 : p->fown.signum = fcntl(lfd, F_GETSIG, 0);
265 : : if (p->fown.signum < 0) {
266 : : pr_perror("Can't get owner signum on %d\n", lfd);
267 : : return -1;
268 : : }
269 : :
270 [ + + ]: 1505 : if (opts->fown.pid == 0)
271 : : return 0;
272 : :
273 : 4 : p->fown.pid = opts->fown.pid;
274 : 4 : p->fown.pid_type = opts->fown.pid_type;
275 : 4 : p->fown.uid = opts->fown.uid;
276 : 4 : p->fown.euid = opts->fown.euid;
277 : :
278 : 1505 : return 0;
279 : : }
280 : :
281 : 0 : static int dump_unsupp_fd(const struct fd_parms *p)
282 : : {
283 : 0 : pr_err("Can't dump file %d of that type [%#x]\n",
284 : : p->fd, p->stat.st_mode);
285 : 0 : return -1;
286 : : }
287 : :
288 : 368 : static int dump_chrdev(struct fd_parms *p, int lfd, const struct cr_fdset *set)
289 : : {
290 : 736 : int maj = major(p->stat.st_rdev);
291 : :
292 [ + + - ]: 368 : switch (maj) {
293 : : case MEM_MAJOR:
294 : 349 : return dump_reg_file(p, lfd, set);
295 : : case TTYAUX_MAJOR:
296 : : case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
297 : : case UNIX98_PTY_SLAVE_MAJOR:
298 : 19 : return dump_tty(p, lfd, set);
299 : : }
300 : :
301 : 368 : return dump_unsupp_fd(p);
302 : : }
303 : :
304 : : #ifndef PIPEFS_MAGIC
305 : : #define PIPEFS_MAGIC 0x50495045
306 : : #endif
307 : :
308 : 1505 : static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_opts *opts,
309 : : const struct cr_fdset *cr_fdset)
310 : : {
311 : : struct fd_parms p;
312 : : struct statfs statfs;
313 : :
314 [ - + ]: 1505 : if (fill_fd_params(ctl, fd, lfd, opts, &p) < 0) {
315 : 0 : pr_perror("Can't get stat on %d", fd);
316 : : return -1;
317 : : }
318 : :
319 [ + + ]: 1505 : if (S_ISSOCK(p.stat.st_mode))
320 : 99 : return dump_socket(&p, lfd, cr_fdset);
321 : :
322 [ + + ]: 1406 : if (S_ISCHR(p.stat.st_mode))
323 : 368 : return dump_chrdev(&p, lfd, cr_fdset);
324 : :
325 [ - + ]: 1038 : if (fstatfs(lfd, &statfs)) {
326 : 0 : pr_perror("Can't obtain statfs on fd %d\n", fd);
327 : : return -1;
328 : : }
329 : :
330 [ + + ]: 1038 : if (is_anon_inode(&statfs)) {
331 [ + + ]: 8 : if (is_eventfd_link(lfd))
332 : 2 : return dump_eventfd(&p, lfd, cr_fdset);
333 [ + + ]: 6 : else if (is_eventpoll_link(lfd))
334 : 2 : return dump_eventpoll(&p, lfd, cr_fdset);
335 [ + + ]: 4 : else if (is_inotify_link(lfd))
336 : 2 : return dump_inotify(&p, lfd, cr_fdset);
337 [ + - ]: 2 : else if (is_signalfd_link(lfd))
338 : 2 : return dump_signalfd(&p, lfd, cr_fdset);
339 : : else
340 : 0 : return dump_unsupp_fd(&p);
341 : : }
342 : :
343 [ + + ]: 1030 : if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode))
344 : 776 : return dump_reg_file(&p, lfd, cr_fdset);
345 : :
346 [ + - ]: 254 : if (S_ISFIFO(p.stat.st_mode)) {
347 [ + + ]: 254 : if (statfs.f_type == PIPEFS_MAGIC)
348 : 238 : return dump_pipe(&p, lfd, cr_fdset);
349 : : else
350 : 16 : return dump_fifo(&p, lfd, cr_fdset);
351 : : }
352 : :
353 : 1505 : return dump_unsupp_fd(&p);
354 : : }
355 : :
356 : 349 : static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdset *cr_fdset,
357 : : struct parasite_drain_fd *dfds)
358 : : {
359 : : int *lfds;
360 : : struct fd_opts *opts;
361 : 349 : int i, ret = -1;
362 : :
363 : 349 : pr_info("\n");
364 : 349 : pr_info("Dumping opened files (pid: %d)\n", ctl->pid);
365 : 349 : pr_info("----------------------------------------\n");
366 : :
367 [ - + ]: 349 : lfds = xmalloc(dfds->nr_fds * sizeof(int));
368 [ + - ]: 349 : if (!lfds)
369 : : goto err;
370 : :
371 [ - + ]: 349 : opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts));
372 [ + - ]: 349 : if (!opts)
373 : : goto err1;
374 : :
375 : 349 : ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
376 [ + - ]: 349 : if (ret)
377 : : goto err2;
378 : :
379 [ + + ]: 1854 : for (i = 0; i < dfds->nr_fds; i++) {
380 : 1505 : ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, cr_fdset);
381 : 1505 : close(lfds[i]);
382 [ + - ]: 1505 : if (ret)
383 : : goto err2;
384 : : }
385 : :
386 : 349 : pr_info("----------------------------------------\n");
387 : : err2:
388 [ + - ]: 349 : xfree(opts);
389 : : err1:
390 [ + - ]: 349 : xfree(lfds);
391 : : err:
392 : 349 : return ret;
393 : : }
394 : :
395 : 349 : static int dump_task_fs(pid_t pid, struct cr_fdset *fdset)
396 : : {
397 : 349 : struct fd_parms p = FD_PARMS_INIT;
398 : 349 : FsEntry fe = FS_ENTRY__INIT;
399 : : int fd, ret;
400 : :
401 [ - + ]: 349 : fd = open_proc(pid, "cwd");
402 [ + - ]: 349 : if (fd < 0)
403 : : return -1;
404 : :
405 [ - + ]: 349 : if (fstat(fd, &p.stat) < 0) {
406 : 0 : pr_perror("Can't stat cwd");
407 : : return -1;
408 : : }
409 : :
410 : 349 : fe.cwd_id = fd_id_generate_special();
411 : :
412 : 349 : ret = dump_one_reg_file(fd, fe.cwd_id, &p);
413 [ + - ]: 349 : if (ret < 0)
414 : : return ret;
415 : :
416 : 349 : close(fd);
417 : :
418 [ - + ]: 349 : fd = open_proc(pid, "root");
419 [ + - ]: 349 : if (fd < 0)
420 : : return -1;
421 : :
422 [ - + ]: 349 : if (fstat(fd, &p.stat) < 0) {
423 : 0 : pr_perror("Can't stat root");
424 : : return -1;
425 : : }
426 : :
427 : 349 : fe.root_id = fd_id_generate_special();
428 : :
429 : 349 : ret = dump_one_reg_file(fd, fe.root_id, &p);
430 [ + - ]: 349 : if (ret < 0)
431 : : return ret;
432 : :
433 : 349 : close(fd);
434 : :
435 : 349 : pr_info("Dumping task cwd id %#x root id %#x\n",
436 : : fe.cwd_id, fe.root_id);
437 : :
438 : 349 : return pb_write_one(fdset_fd(fdset, CR_FD_FS), &fe, PB_FS);
439 : : }
440 : :
441 : 3277 : static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
442 : : const struct cr_fdset *fdset)
443 : : {
444 : 3277 : struct fd_parms p = FD_PARMS_INIT;
445 : :
446 [ - + ]: 3277 : if (fstat(file_fd, &p.stat) < 0) {
447 : 0 : pr_perror("Can't stat file for vma");
448 : : return -1;
449 : : }
450 : :
451 [ + + ][ + + ]: 3277 : if ((vma->prot & PROT_WRITE) && vma_entry_is(vma, VMA_FILE_SHARED))
452 : 4 : p.flags = O_RDWR;
453 : : else
454 : 3273 : p.flags = O_RDONLY;
455 : 3277 : vma->shmid = fd_id_generate_special();
456 : :
457 : 3277 : return dump_one_reg_file(file_fd, vma->shmid, &p);
458 : : }
459 : :
460 : 349 : static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
461 : : const struct cr_fdset *cr_fdset)
462 : : {
463 : : struct vma_area *vma_area;
464 : 349 : int ret = -1, fd;
465 : :
466 : 349 : pr_info("\n");
467 : 349 : pr_info("Dumping mappings (pid: %d)\n", pid);
468 : 349 : pr_info("----------------------------------------\n");
469 : :
470 : 349 : fd = fdset_fd(cr_fdset, CR_FD_VMAS);
471 : :
472 [ + + ]: 6404 : list_for_each_entry(vma_area, vma_area_list, list) {
473 : 6055 : VmaEntry *vma = &vma_area->vma;
474 : :
475 : 6055 : pr_info_vma(vma_area);
476 : :
477 [ + + ]: 6055 : if (!vma_entry_is(vma, VMA_AREA_REGULAR) ||
478 : : vma_entry_is(vma, VMA_AREA_SYSVIPC))
479 : : ret = 0;
480 [ + + ]: 5701 : else if (vma_entry_is(vma, VMA_ANON_SHARED))
481 : 44 : ret = add_shmem_area(pid, vma);
482 [ + + ]: 5657 : else if (vma_entry_is(vma, VMA_FILE_PRIVATE) ||
483 : : vma_entry_is(vma, VMA_FILE_SHARED))
484 : 3277 : ret = dump_filemap(pid, vma, vma_area->vm_file_fd, cr_fdset);
485 [ - + ]: 2380 : else if (vma_entry_is(vma, VMA_AREA_SOCKET))
486 : 0 : ret = dump_socket_map(vma_area);
487 : : else
488 : : ret = 0;
489 : :
490 [ + - ]: 6055 : if (!ret)
491 : 6055 : ret = pb_write_one(fd, vma, PB_VMAS);
492 [ + - ]: 6055 : if (ret)
493 : : goto err;
494 : : }
495 : :
496 : 349 : ret = 0;
497 : 349 : pr_info("----------------------------------------\n");
498 : : err:
499 : 349 : return ret;
500 : : }
501 : :
502 : : extern int capget(cap_user_header_t header, const cap_user_data_t data);
503 : 349 : static int dump_task_creds(struct parasite_ctl *ctl, const struct cr_fdset *fds)
504 : : {
505 : : int ret, i;
506 : : struct proc_status_creds cr;
507 : 349 : CredsEntry ce = CREDS_ENTRY__INIT;
508 : :
509 : : struct __user_cap_data_struct data[2];
510 : 698 : struct __user_cap_header_struct hdr = {
511 : : .version = _LINUX_CAPABILITY_VERSION_3,
512 : 349 : .pid = ctl->pid
513 : : };
514 : :
515 : 349 : pr_info("\n");
516 : 349 : pr_info("Dumping creds for %d)\n", ctl->pid);
517 : 349 : pr_info("----------------------------------------\n");
518 : :
519 : 349 : ret = parse_pid_status(ctl->pid, &cr);
520 [ + - ]: 349 : if (ret < 0)
521 : : return ret;
522 : :
523 : 349 : ce.uid = cr.uids[0];
524 : 349 : ce.gid = cr.gids[0];
525 : 349 : ce.euid = cr.uids[1];
526 : 349 : ce.egid = cr.gids[1];
527 : 349 : ce.suid = cr.uids[2];
528 : 349 : ce.sgid = cr.gids[2];
529 : 349 : ce.fsuid = cr.uids[3];
530 : 349 : ce.fsgid = cr.gids[3];
531 : :
532 : : BUILD_BUG_ON(CR_CAP_SIZE != PROC_CAP_SIZE);
533 : :
534 [ - + ]: 349 : if (capget(&hdr, data)) {
535 : 0 : pr_perror("Unable to get capabilities");
536 : : return -1;
537 : : }
538 : :
539 [ - + ]: 349 : ce.cap_inh = xmalloc(sizeof(uint32_t) * CR_CAP_SIZE);
540 [ - + ]: 349 : ce.cap_prm = xmalloc(sizeof(uint32_t) * CR_CAP_SIZE);
541 [ - + ]: 349 : ce.cap_eff = xmalloc(sizeof(uint32_t) * CR_CAP_SIZE);
542 [ + - ][ + - ]: 349 : if (!ce.cap_inh || !ce.cap_prm || !ce.cap_eff)
[ + - ]
543 : : return -1;
544 : :
545 : 349 : ce.n_cap_inh = CR_CAP_SIZE;
546 : 349 : ce.n_cap_prm = CR_CAP_SIZE;
547 : 349 : ce.n_cap_eff = CR_CAP_SIZE;
548 : :
549 [ + + ]: 1047 : for (i = 0; i < 2; i++) {
550 : 698 : ce.cap_inh[i] = data[i].inheritable;
551 : 698 : ce.cap_prm[i] = data[i].permitted;
552 : 698 : ce.cap_eff[i] = data[i].effective;
553 : : }
554 : :
555 : 349 : ce.n_cap_bnd = CR_CAP_SIZE;
556 : 349 : ce.cap_bnd = cr.cap_bnd;
557 : :
558 [ + - ]: 349 : if (parasite_dump_creds(ctl, &ce) < 0)
559 : : return -1;
560 : :
561 : 349 : ret = pb_write_one(fdset_fd(fds, CR_FD_CREDS), &ce, PB_CREDS);
562 : :
563 [ + - ]: 349 : xfree(ce.cap_inh);
564 [ + - ]: 349 : xfree(ce.cap_prm);
565 [ + - ]: 349 : xfree(ce.cap_eff);
566 : : return ret;
567 : : }
568 : :
569 : 349 : static int get_task_auxv(pid_t pid, MmEntry *mm, size_t *size)
570 : : {
571 : : int fd, ret, i;
572 : :
573 : 349 : pr_info("Obtainting task auvx ... ");
574 : :
575 [ - + ]: 349 : fd = open_proc(pid, "auxv");
576 [ + - ]: 349 : if (fd < 0)
577 : : return -1;
578 : :
579 [ + - ]: 13611 : for (i = 0; i < AT_VECTOR_SIZE; i++) {
580 : 13611 : ret = read(fd, &mm->mm_saved_auxv[i],
581 : : sizeof(mm->mm_saved_auxv[0]));
582 [ + + ]: 13611 : if (ret == 0)
583 : : break;
584 [ - + ]: 13262 : else if (ret != sizeof(mm->mm_saved_auxv[0])) {
585 : 0 : ret = -1;
586 : 0 : pr_perror("Error readind %d's auxv[%d]",
587 : : pid, i);
588 : : goto err;
589 : : }
590 : : }
591 : :
592 : 349 : *size = i;
593 : 349 : ret = 0;
594 : : err:
595 : 349 : close_safe(&fd);
596 : : return ret;
597 : : }
598 : :
599 : 349 : static int dump_task_mm(pid_t pid, const struct proc_pid_stat *stat,
600 : : const struct parasite_dump_misc *misc, const struct cr_fdset *fdset)
601 : : {
602 : 349 : MmEntry mme = MM_ENTRY__INIT;
603 : 349 : int ret = -1;
604 : :
605 : 349 : mme.mm_start_code = stat->start_code;
606 : 349 : mme.mm_end_code = stat->end_code;
607 : 349 : mme.mm_start_data = stat->start_data;
608 : 349 : mme.mm_end_data = stat->end_data;
609 : 349 : mme.mm_start_stack = stat->start_stack;
610 : 349 : mme.mm_start_brk = stat->start_brk;
611 : :
612 : 349 : mme.mm_arg_start = stat->arg_start;
613 : 349 : mme.mm_arg_end = stat->arg_end;
614 : 349 : mme.mm_env_start = stat->env_start;
615 : 349 : mme.mm_env_end = stat->env_end;
616 : :
617 : 349 : mme.mm_brk = misc->brk;
618 : :
619 : 349 : mme.n_mm_saved_auxv = AT_VECTOR_SIZE;
620 [ - + ]: 349 : mme.mm_saved_auxv = xmalloc(pb_repeated_size(&mme, mm_saved_auxv));
621 [ + - ]: 349 : if (!mme.mm_saved_auxv)
622 : : goto out;
623 : :
624 [ + - ]: 349 : if (get_task_auxv(pid, &mme, &mme.n_mm_saved_auxv))
625 : : goto out;
626 : 349 : pr_info("OK\n");
627 : :
628 [ + - ]: 349 : if (dump_task_exe_link(pid, &mme))
629 : : goto out;
630 : :
631 : 349 : ret = pb_write_one(fdset_fd(fdset, CR_FD_MM), &mme, PB_MM);
632 [ + - ]: 349 : xfree(mme.mm_saved_auxv);
633 : : out:
634 : 349 : return ret;
635 : : }
636 : :
637 : 381 : static int get_task_futex_robust_list(pid_t pid, ThreadCoreEntry *info)
638 : : {
639 : 381 : struct robust_list_head *head = NULL;
640 : 381 : size_t len = 0;
641 : : int ret;
642 : :
643 : 381 : ret = sys_get_robust_list(pid, &head, &len);
644 [ - + ]: 381 : if (ret) {
645 : 0 : pr_err("Failed obtaining futex robust list on %d\n", pid);
646 : : return -1;
647 : : }
648 : :
649 : 381 : info->futex_rla = (u64)head;
650 : 381 : info->futex_rla_len = (u32)len;
651 : :
652 : : return 0;
653 : : }
654 : :
655 : 349 : static int get_task_personality(pid_t pid, u32 *personality)
656 : : {
657 : 349 : FILE *file = NULL;
658 : 349 : int ret = -1;
659 : :
660 : 349 : pr_info("Obtainting personality ... ");
661 : :
662 [ + - ][ - + ]: 349 : file = fopen_proc(pid, "personality");
[ - + ]
663 [ + - ]: 349 : if (!file)
664 : : goto err;
665 : :
666 [ - + ]: 349 : if (!fgets(loc_buf, sizeof(loc_buf), file)) {
667 : 0 : pr_perror("Can't read task personality");
668 : 0 : goto err;
669 : : }
670 : :
671 : 349 : *personality = atoi(loc_buf);
672 : 349 : ret = 0;
673 : :
674 : : err:
675 [ + - ]: 349 : if (file)
676 : 349 : fclose(file);
677 : 349 : return ret;
678 : : }
679 : :
680 : 381 : static int get_task_regs(pid_t pid, CoreEntry *core, const struct parasite_ctl *ctl)
681 : : {
682 : 381 : struct xsave_struct xsave = { };
683 : 381 : user_regs_struct_t regs = {-1};
684 : :
685 : : struct iovec iov;
686 : 381 : int ret = -1;
687 : :
688 : 381 : pr_info("Dumping GP/FPU registers ... ");
689 : :
690 [ + + ]: 381 : if (ctl)
691 : 349 : regs = ctl->regs_orig;
692 : : else {
693 [ - + ]: 32 : if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) {
694 : 0 : pr_err("Can't obtain GP registers for %d\n", pid);
695 : : goto err;
696 : : }
697 : : }
698 : :
699 : : /* Did we come from a system call? */
700 [ + + ]: 381 : if ((int)regs.orig_ax >= 0) {
701 : : /* Restart the system call */
702 [ + + + ]: 373 : switch ((long)(int)regs.ax) {
703 : : case -ERESTARTNOHAND:
704 : : case -ERESTARTSYS:
705 : : case -ERESTARTNOINTR:
706 : 337 : regs.ax = regs.orig_ax;
707 : 337 : regs.ip -= 2;
708 : : break;
709 : : case -ERESTART_RESTARTBLOCK:
710 : 8 : regs.ax = __NR_restart_syscall;
711 : 8 : regs.ip -= 2;
712 : : break;
713 : : }
714 : : }
715 : :
716 : : #define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0)
717 : : #define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e))
718 : :
719 : 381 : assign_reg(core->thread_info->gpregs, regs, r15);
720 : 381 : assign_reg(core->thread_info->gpregs, regs, r14);
721 : 381 : assign_reg(core->thread_info->gpregs, regs, r13);
722 : 381 : assign_reg(core->thread_info->gpregs, regs, r12);
723 : 381 : assign_reg(core->thread_info->gpregs, regs, bp);
724 : 381 : assign_reg(core->thread_info->gpregs, regs, bx);
725 : 381 : assign_reg(core->thread_info->gpregs, regs, r11);
726 : 381 : assign_reg(core->thread_info->gpregs, regs, r10);
727 : 381 : assign_reg(core->thread_info->gpregs, regs, r9);
728 : 381 : assign_reg(core->thread_info->gpregs, regs, r8);
729 : 381 : assign_reg(core->thread_info->gpregs, regs, ax);
730 : 381 : assign_reg(core->thread_info->gpregs, regs, cx);
731 : 381 : assign_reg(core->thread_info->gpregs, regs, dx);
732 : 381 : assign_reg(core->thread_info->gpregs, regs, si);
733 : 381 : assign_reg(core->thread_info->gpregs, regs, di);
734 : 381 : assign_reg(core->thread_info->gpregs, regs, orig_ax);
735 : 381 : assign_reg(core->thread_info->gpregs, regs, ip);
736 : 381 : assign_reg(core->thread_info->gpregs, regs, cs);
737 : 381 : assign_reg(core->thread_info->gpregs, regs, flags);
738 : 381 : assign_reg(core->thread_info->gpregs, regs, sp);
739 : 381 : assign_reg(core->thread_info->gpregs, regs, ss);
740 : 381 : assign_reg(core->thread_info->gpregs, regs, fs_base);
741 : 381 : assign_reg(core->thread_info->gpregs, regs, gs_base);
742 : 381 : assign_reg(core->thread_info->gpregs, regs, ds);
743 : 381 : assign_reg(core->thread_info->gpregs, regs, es);
744 : 381 : assign_reg(core->thread_info->gpregs, regs, fs);
745 : 381 : assign_reg(core->thread_info->gpregs, regs, gs);
746 : :
747 : : #ifndef PTRACE_GETREGSET
748 : : # define PTRACE_GETREGSET 0x4204
749 : : #endif
750 : :
751 [ + - ]: 381 : if (!cpu_has_feature(X86_FEATURE_FPU))
752 : : goto out;
753 : :
754 : : /*
755 : : * FPU fetched either via fxsave or via xsave,
756 : : * thus decode it accrodingly.
757 : : */
758 : :
759 [ - + ]: 381 : if (cpu_has_feature(X86_FEATURE_XSAVE)) {
760 : 0 : iov.iov_base = &xsave;
761 : 0 : iov.iov_len = sizeof(xsave);
762 : :
763 [ # # ]: 0 : if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) {
764 : 0 : pr_err("Can't obtain FPU registers for %d\n", pid);
765 : : goto err;
766 : : }
767 : : } else {
768 [ - + ]: 381 : if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) {
769 : 0 : pr_err("Can't obtain FPU registers for %d\n", pid);
770 : : goto err;
771 : : }
772 : : }
773 : :
774 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, cwd);
775 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, swd);
776 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, twd);
777 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, fop);
778 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, rip);
779 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, rdp);
780 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr);
781 : 381 : assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr_mask);
782 : :
783 : : /* Make sure we have enough space */
784 [ - + ]: 381 : BUG_ON(core->thread_info->fpregs->n_st_space != ARRAY_SIZE(xsave.i387.st_space));
785 [ - + ]: 381 : BUG_ON(core->thread_info->fpregs->n_xmm_space != ARRAY_SIZE(xsave.i387.xmm_space));
786 : :
787 : 381 : assign_array(core->thread_info->fpregs, xsave.i387, st_space);
788 : 381 : assign_array(core->thread_info->fpregs, xsave.i387, xmm_space);
789 : :
790 [ - + ]: 381 : if (cpu_has_feature(X86_FEATURE_XSAVE)) {
791 [ # # ]: 0 : BUG_ON(core->thread_info->fpregs->xsave->n_ymmh_space != ARRAY_SIZE(xsave.ymmh.ymmh_space));
792 : :
793 : 0 : assign_reg(core->thread_info->fpregs->xsave, xsave.xsave_hdr, xstate_bv);
794 : 0 : assign_array(core->thread_info->fpregs->xsave, xsave.ymmh, ymmh_space);
795 : : }
796 : :
797 : : #undef assign_reg
798 : : #undef assign_array
799 : :
800 : : out:
801 : : ret = 0;
802 : :
803 : : err:
804 : 381 : return ret;
805 : : }
806 : :
807 : : static DECLARE_KCMP_TREE(vm_tree, KCMP_VM);
808 : : static DECLARE_KCMP_TREE(fs_tree, KCMP_FS);
809 : : static DECLARE_KCMP_TREE(files_tree, KCMP_FILES);
810 : : static DECLARE_KCMP_TREE(sighand_tree, KCMP_SIGHAND);
811 : :
812 : 349 : static int dump_task_kobj_ids(pid_t pid, CoreEntry *core)
813 : : {
814 : : int new;
815 : : struct kid_elem elem;
816 : :
817 : 349 : elem.pid = pid;
818 : 349 : elem.idx = 0; /* really 0 for all */
819 : 349 : elem.genid = 0; /* FIXME optimize */
820 : :
821 : 349 : new = 0;
822 : 349 : core->ids->vm_id = kid_generate_gen(&vm_tree, &elem, &new);
823 [ - + ][ + - ]: 349 : if (!core->ids->vm_id || !new) {
824 : 0 : pr_err("Can't make VM id for %d\n", pid);
825 : : return -1;
826 : : }
827 : :
828 : 349 : new = 0;
829 : 349 : core->ids->fs_id = kid_generate_gen(&fs_tree, &elem, &new);
830 [ - + ][ + - ]: 349 : if (!core->ids->fs_id || !new) {
831 : 0 : pr_err("Can't make FS id for %d\n", pid);
832 : : return -1;
833 : : }
834 : :
835 : 349 : new = 0;
836 : 349 : core->ids->files_id = kid_generate_gen(&files_tree, &elem, &new);
837 [ - + ][ + - ]: 349 : if (!core->ids->files_id || !new) {
838 : 0 : pr_err("Can't make FILES id for %d\n", pid);
839 : : return -1;
840 : : }
841 : :
842 : 349 : new = 0;
843 : 349 : core->ids->sighand_id = kid_generate_gen(&sighand_tree, &elem, &new);
844 [ - + ][ + - ]: 349 : if (!core->ids->sighand_id || !new) {
845 : 349 : pr_err("Can't make IO id for %d\n", pid);
846 : : return -1;
847 : : }
848 : :
849 : : return 0;
850 : : }
851 : :
852 : 391 : static void core_entry_free(CoreEntry *core)
853 : : {
854 [ + - ]: 391 : if (core) {
855 [ + + ]: 391 : if (core->thread_info) {
856 [ + - ]: 381 : if (core->thread_info->fpregs) {
857 [ - + ]: 381 : if (core->thread_info->fpregs->xsave)
858 [ # # ]: 0 : xfree(core->thread_info->fpregs->xsave->ymmh_space);
859 [ - + ]: 381 : xfree(core->thread_info->fpregs->xsave);
860 [ + - ]: 381 : xfree(core->thread_info->fpregs->st_space);
861 [ + - ]: 381 : xfree(core->thread_info->fpregs->xmm_space);
862 [ - + ]: 381 : xfree(core->thread_info->fpregs->padding);
863 : : }
864 [ + - ]: 381 : xfree(core->thread_info->gpregs);
865 [ + - ]: 381 : xfree(core->thread_info->fpregs);
866 : : }
867 [ + + ]: 391 : xfree(core->thread_info);
868 [ + + ]: 391 : xfree(core->thread_core);
869 [ + + ]: 391 : xfree(core->tc);
870 [ + + ]: 391 : xfree(core->ids);
871 : : }
872 : 391 : }
873 : :
874 : 391 : static CoreEntry *core_entry_alloc(int alloc_thread_info,
875 : : int alloc_tc,
876 : : int alloc_ids)
877 : : {
878 : : CoreEntry *core;
879 : : ThreadInfoX86 *thread_info;
880 : : UserX86RegsEntry *gpregs;
881 : : UserX86FpregsEntry *fpregs;
882 : : TaskCoreEntry *tc;
883 : : TaskKobjIdsEntry *ids;
884 : : ThreadCoreEntry *thread_core;
885 : :
886 [ - + ]: 391 : core = xmalloc(sizeof(*core));
887 [ + - ]: 391 : if (!core)
888 : : return NULL;
889 : 391 : core_entry__init(core);
890 : :
891 : 391 : core->mtype = CORE_ENTRY__MARCH__X86_64;
892 : :
893 [ + + ]: 391 : if (alloc_thread_info) {
894 [ - + ]: 381 : thread_info = xmalloc(sizeof(*thread_info));
895 [ + - ]: 381 : if (!thread_info)
896 : : goto err;
897 : 381 : thread_info_x86__init(thread_info);
898 : 381 : core->thread_info = thread_info;
899 : :
900 [ - + ]: 381 : thread_core = xmalloc(sizeof(*thread_core));
901 [ + - ]: 381 : if (!thread_core)
902 : : goto err;
903 : 381 : thread_core_entry__init(thread_core);
904 : 381 : core->thread_core = thread_core;
905 : :
906 [ - + ]: 381 : gpregs = xmalloc(sizeof(*gpregs));
907 [ + - ]: 381 : if (!gpregs)
908 : : goto err;
909 : 381 : user_x86_regs_entry__init(gpregs);
910 : 381 : thread_info->gpregs = gpregs;
911 : :
912 [ + - ]: 381 : if (cpu_has_feature(X86_FEATURE_FPU)) {
913 [ - + ]: 381 : fpregs = xmalloc(sizeof(*fpregs));
914 [ + - ]: 381 : if (!fpregs)
915 : : goto err;
916 : 381 : user_x86_fpregs_entry__init(fpregs);
917 : 381 : thread_info->fpregs = fpregs;
918 : :
919 : : /* These are numbers from kernel */
920 : 381 : fpregs->n_st_space = 32;
921 : 381 : fpregs->n_xmm_space = 64;
922 : :
923 [ - + ]: 381 : fpregs->st_space = xzalloc(pb_repeated_size(fpregs, st_space));
924 [ - + ]: 381 : fpregs->xmm_space = xzalloc(pb_repeated_size(fpregs, xmm_space));
925 : :
926 [ + - ][ + - ]: 381 : if (!fpregs->st_space || !fpregs->xmm_space)
927 : : goto err;
928 : :
929 [ - + ]: 381 : if (cpu_has_feature(X86_FEATURE_XSAVE)) {
930 : : UserX86XsaveEntry *xsave;
931 [ # # ]: 0 : xsave = xmalloc(sizeof(*xsave));
932 [ # # ]: 0 : if (!xsave)
933 : : goto err;
934 : 0 : user_x86_xsave_entry__init(xsave);
935 : 0 : thread_info->fpregs->xsave = xsave;
936 : :
937 : 0 : xsave->n_ymmh_space = 64;
938 [ # # ]: 0 : xsave->ymmh_space = xzalloc(pb_repeated_size(xsave, ymmh_space));
939 [ # # ]: 0 : if (!xsave->ymmh_space)
940 : : goto err;
941 : : }
942 : : }
943 : : }
944 : :
945 [ + + ]: 391 : if (alloc_tc) {
946 [ - + ]: 359 : tc = xzalloc(sizeof(*tc) + TASK_COMM_LEN);
947 [ + - ]: 359 : if (!tc)
948 : : goto err;
949 : 359 : task_core_entry__init(tc);
950 : 359 : tc->comm = (void *)tc + sizeof(*tc);
951 : 359 : core->tc = tc;
952 : : }
953 : :
954 [ + + ]: 391 : if (alloc_ids) {
955 [ - + ]: 349 : ids = xmalloc(sizeof(*ids));
956 [ + - ]: 349 : if (!ids)
957 : : goto err;
958 : 349 : task_kobj_ids_entry__init(ids);
959 : 349 : core->ids = ids;
960 : : }
961 : :
962 : 391 : return core;
963 : : err:
964 : 0 : core_entry_free(core);
965 : 391 : return NULL;
966 : : }
967 : :
968 : 349 : static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
969 : : const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
970 : : const struct cr_fdset *cr_fdset,
971 : : struct list_head *vma_area_list)
972 : : {
973 : 349 : int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
974 : : CoreEntry *core;
975 : 349 : int ret = -1;
976 : :
977 : 349 : core = core_entry_alloc(1, 1, 1);
978 [ + - ]: 349 : if (!core)
979 : : return -1;
980 : :
981 : 349 : pr_info("\n");
982 : 349 : pr_info("Dumping core (pid: %d)\n", pid);
983 : 349 : pr_info("----------------------------------------\n");
984 : :
985 : 349 : ret = dump_task_kobj_ids(pid, core);
986 [ + - ]: 349 : if (ret)
987 : : goto err_free;
988 : :
989 : 349 : ret = dump_task_mm(pid, stat, misc, cr_fdset);
990 [ + - ]: 349 : if (ret)
991 : : goto err_free;
992 : :
993 : 349 : ret = get_task_regs(pid, core, ctl);
994 [ + - ]: 349 : if (ret)
995 : : goto err_free;
996 : :
997 : 349 : mark_stack_vma(core->thread_info->gpregs->sp, vma_area_list);
998 : :
999 : 349 : ret = get_task_futex_robust_list(pid, core->thread_core);
1000 [ + - ]: 349 : if (ret)
1001 : : goto err_free;
1002 : :
1003 : 349 : ret = get_task_personality(pid, &core->tc->personality);
1004 [ + - ]: 349 : if (ret)
1005 : : goto err_free;
1006 : :
1007 : 349 : strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
1008 : 349 : core->tc->flags = stat->flags;
1009 : : BUILD_BUG_ON(sizeof(core->tc->blk_sigset) != sizeof(k_rtsigset_t));
1010 : 349 : memcpy(&core->tc->blk_sigset, &misc->blocked, sizeof(k_rtsigset_t));
1011 : :
1012 : 349 : core->tc->task_state = TASK_ALIVE;
1013 : 349 : core->tc->exit_code = 0;
1014 : :
1015 : 349 : ret = dump_sched_info(pid, core->thread_core);
1016 [ + - ]: 349 : if (ret)
1017 : : goto err_free;
1018 : :
1019 : 349 : ret = pb_write_one(fd_core, core, PB_CORE);
1020 : : if (ret < 0)
1021 : : goto err_free;
1022 : :
1023 : : err_free:
1024 : 349 : core_entry_free(core);
1025 : 349 : pr_info("----------------------------------------\n");
1026 : :
1027 : 349 : return ret;
1028 : : }
1029 : :
1030 : 718 : static int parse_threads(const struct pstree_item *item, struct pid **_t, int *_n)
1031 : : {
1032 : : struct dirent *de;
1033 : : DIR *dir;
1034 : 718 : struct pid *t = NULL;
1035 : 718 : int nr = 1;
1036 : :
1037 [ - + ][ + - ]: 718 : dir = opendir_proc(item->pid.real, "task");
[ - + ]
1038 [ + - ]: 718 : if (!dir)
1039 : : return -1;
1040 : :
1041 [ + + ]: 2936 : while ((de = readdir(dir))) {
1042 : : struct pid *tmp;
1043 : :
1044 : : /* We expect numbers only here */
1045 [ + + ]: 2218 : if (de->d_name[0] == '.')
1046 : 1436 : continue;
1047 : :
1048 [ - + ]: 782 : tmp = xrealloc(t, nr * sizeof(struct pid));
1049 [ - + ]: 782 : if (!tmp) {
1050 [ # # ]: 0 : xfree(t);
1051 : : return -1;
1052 : : }
1053 : 782 : t = tmp;
1054 : 1564 : t[nr - 1].real = atoi(de->d_name);
1055 : 782 : t[nr - 1].virt = -1;
1056 : 2218 : nr++;
1057 : : }
1058 : :
1059 : 718 : closedir(dir);
1060 : :
1061 : 718 : *_t = t;
1062 : 718 : *_n = nr - 1;
1063 : :
1064 : : return 0;
1065 : : }
1066 : :
1067 : 359 : static int get_threads(struct pstree_item *item)
1068 : : {
1069 : 359 : return parse_threads(item, &item->threads, &item->nr_threads);
1070 : : }
1071 : :
1072 : 359 : static int check_threads(const struct pstree_item *item)
1073 : : {
1074 : : struct pid *t;
1075 : : int nr, ret;
1076 : :
1077 : 359 : ret = parse_threads(item, &t, &nr);
1078 [ + - ]: 359 : if (ret)
1079 : : return ret;
1080 : :
1081 [ + - ][ - + ]: 359 : ret = ((nr == item->nr_threads) && !memcmp(t, item->threads, nr));
1082 [ + - ]: 359 : xfree(t);
1083 : :
1084 [ - + ]: 359 : if (!ret) {
1085 : 359 : pr_info("Threads set has changed while suspending\n");
1086 : : return -1;
1087 : : }
1088 : :
1089 : : return 0;
1090 : : }
1091 : :
1092 : 796 : static int parse_children(pid_t pid, pid_t **_c, int *_n)
1093 : : {
1094 : : FILE *file;
1095 : : char *tok;
1096 : 796 : pid_t *ch = NULL;
1097 : 796 : int nr = 1;
1098 : : DIR *dir;
1099 : : struct dirent *de;
1100 : :
1101 [ - + ][ + - ]: 796 : dir = opendir_proc(pid, "task");
[ - + ]
1102 [ + - ]: 796 : if (dir == NULL)
1103 : : return -1;
1104 : :
1105 [ + + ]: 3248 : while ((de = readdir(dir))) {
1106 [ + + ]: 2452 : if (dir_dots(de))
1107 : 1592 : continue;
1108 : :
1109 [ - + ][ + - ]: 860 : file = fopen_proc(pid, "task/%s/children", de->d_name);
[ - + ]
1110 [ + - ]: 860 : if (!file)
1111 : : goto err;
1112 : :
1113 [ + + ]: 860 : if (!(fgets(loc_buf, sizeof(loc_buf), file)))
1114 : 510 : loc_buf[0] = 0;
1115 : :
1116 : 860 : fclose(file);
1117 : :
1118 : 860 : tok = strtok(loc_buf, " \n");
1119 [ + + ]: 2923 : while (tok) {
1120 [ - + ]: 471 : pid_t *tmp = xrealloc(ch, nr * sizeof(pid_t));
1121 [ + - ]: 471 : if (!tmp)
1122 : : goto err;
1123 : 471 : ch = tmp;
1124 : 942 : ch[nr - 1] = atoi(tok);
1125 : 471 : nr++;
1126 : 471 : tok = strtok(NULL, " \n");
1127 : : }
1128 : :
1129 : : }
1130 : :
1131 : 796 : *_c = ch;
1132 : 796 : *_n = nr - 1;
1133 : :
1134 : 796 : closedir(dir);
1135 : 796 : return 0;
1136 : : err:
1137 : 0 : closedir(dir);
1138 [ # # ]: 796 : xfree(ch);
1139 : : return -1;
1140 : : }
1141 : :
1142 : 359 : static int get_children(struct pstree_item *item)
1143 : : {
1144 : : pid_t *ch;
1145 : : int ret, i, nr_children;
1146 : : struct pstree_item *c;
1147 : :
1148 : 359 : ret = parse_children(item->pid.real, &ch, &nr_children);
1149 [ + - ]: 359 : if (ret < 0)
1150 : : return ret;
1151 : :
1152 [ + + ]: 552 : for (i = 0; i < nr_children; i++) {
1153 : 193 : c = alloc_pstree_item();
1154 [ + - ]: 193 : if (c == NULL) {
1155 : : ret = -1;
1156 : : goto free;
1157 : : }
1158 : 193 : c->pid.real = ch[i];
1159 : 193 : c->parent = item;
1160 : 193 : list_add_tail(&c->sibling, &item->children);
1161 : : }
1162 : : free:
1163 [ + + ]: 359 : xfree(ch);
1164 : : return ret;
1165 : : }
1166 : :
1167 : 359 : static void unseize_task_and_threads(const struct pstree_item *item, int st)
1168 : : {
1169 : : int i;
1170 : :
1171 [ + + ]: 750 : for (i = 0; i < item->nr_threads; i++)
1172 : 391 : unseize_task(item->threads[i].real, st); /* item->pid will be here */
1173 : 359 : }
1174 : :
1175 : 166 : static void pstree_switch_state(struct pstree_item *root_item, int st)
1176 : : {
1177 : 166 : struct pstree_item *item = root_item;
1178 : :
1179 : 166 : pr_info("Unfreezing tasks into %d\n", st);
1180 [ + + ]: 525 : for_each_pstree_item(item)
1181 : 359 : unseize_task_and_threads(item, st);
1182 : 166 : }
1183 : :
1184 : : static pid_t item_ppid(const struct pstree_item *item)
1185 : : {
1186 : 391 : item = item->parent;
1187 [ + + ][ + + ]: 391 : return item ? item->pid.real : -1;
1188 : : }
1189 : :
1190 : 359 : static int seize_threads(const struct pstree_item *item)
1191 : : {
1192 : 359 : int i = 0, ret;
1193 : :
1194 [ + + ][ + - ]: 359 : if ((item->state == TASK_DEAD) && (item->nr_threads > 1)) {
1195 : 0 : pr_err("Zombies with threads are not supported\n");
1196 : 0 : goto err;
1197 : : }
1198 : :
1199 [ + + ]: 750 : for (i = 0; i < item->nr_threads; i++) {
1200 : 391 : pid_t pid = item->threads[i].real;
1201 [ + + ]: 391 : if (item->pid.real == pid)
1202 : 359 : continue;
1203 : :
1204 : 32 : pr_info("\tSeizing %d's %d thread\n",
1205 : : item->pid.real, pid);
1206 : 32 : ret = seize_task(pid, item_ppid(item), NULL, NULL);
1207 [ + - ]: 32 : if (ret < 0)
1208 : : goto err;
1209 : :
1210 [ - + ]: 32 : if (ret == TASK_DEAD) {
1211 : 0 : pr_err("Zombie thread not supported\n");
1212 : 0 : goto err;
1213 : : }
1214 : :
1215 [ - + ]: 32 : if (ret == TASK_STOPPED) {
1216 : 0 : pr_err("Stopped threads not supported\n");
1217 : 0 : goto err;
1218 : : }
1219 : : }
1220 : :
1221 : : return 0;
1222 : :
1223 : : err:
1224 [ # # ]: 359 : for (i--; i >= 0; i--) {
1225 [ # # ]: 0 : if (item->pid.real == item->threads[i].real)
1226 : 0 : continue;
1227 : :
1228 : 0 : unseize_task(item->threads[i].real, TASK_ALIVE);
1229 : : }
1230 : :
1231 : : return -1;
1232 : : }
1233 : :
1234 : 359 : static int collect_threads(struct pstree_item *item)
1235 : : {
1236 : : int ret;
1237 : :
1238 : 359 : ret = get_threads(item);
1239 [ + - ]: 359 : if (!ret)
1240 : 359 : ret = seize_threads(item);
1241 [ + - ]: 359 : if (!ret)
1242 : 359 : ret = check_threads(item);
1243 : :
1244 : 359 : return ret;
1245 : : }
1246 : :
1247 : 359 : static int collect_task(struct pstree_item *item)
1248 : : {
1249 : : int ret;
1250 : 359 : pid_t pid = item->pid.real;
1251 : :
1252 : 359 : ret = seize_task(pid, item_ppid(item), &item->pgid, &item->sid);
1253 [ + - ]: 359 : if (ret < 0)
1254 : : goto err;
1255 : :
1256 : 359 : pr_info("Seized task %d, state %d\n", pid, ret);
1257 : 359 : item->state = ret;
1258 : :
1259 : 359 : ret = collect_threads(item);
1260 [ + - ]: 359 : if (ret < 0)
1261 : : goto err_close;
1262 : :
1263 : 359 : ret = get_children(item);
1264 [ + - ]: 359 : if (ret < 0)
1265 : : goto err_close;
1266 : :
1267 [ + + ][ - + ]: 359 : if ((item->state == TASK_DEAD) && !list_empty(&item->children)) {
1268 : 0 : pr_err("Zombie with children?! O_o Run, run, run!\n");
1269 : 0 : goto err_close;
1270 : : }
1271 : :
1272 : 359 : close_pid_proc();
1273 : :
1274 : 359 : pr_info("Collected %d in %d state\n", item->pid.real, item->state);
1275 : 359 : return 0;
1276 : :
1277 : : err_close:
1278 : 0 : close_pid_proc();
1279 : 359 : unseize_task(pid, item->state);
1280 : : err:
1281 : : return -1;
1282 : : }
1283 : :
1284 : 435 : static int check_subtree(const struct pstree_item *item)
1285 : : {
1286 : : pid_t *ch;
1287 : : int nr, ret, i;
1288 : : struct pstree_item *child;
1289 : :
1290 : 435 : ret = parse_children(item->pid.real, &ch, &nr);
1291 [ + - ]: 435 : if (ret < 0)
1292 : : return ret;
1293 : :
1294 : 435 : i = 0;
1295 [ + + ]: 708 : list_for_each_entry(child, &item->children, sibling) {
1296 [ + - ]: 273 : if (child->pid.real != ch[i])
1297 : : break;
1298 : 273 : i++;
1299 [ + - ]: 273 : if (i > nr)
1300 : : break;
1301 : : }
1302 [ + + ]: 435 : xfree(ch);
1303 : :
1304 [ - + ]: 435 : if (i != nr) {
1305 : 435 : pr_info("Children set has changed while suspending\n");
1306 : : return -1;
1307 : : }
1308 : :
1309 : : return 0;
1310 : : }
1311 : :
1312 : 359 : static int collect_subtree(struct pstree_item *item)
1313 : : {
1314 : : struct pstree_item *child;
1315 : 359 : pid_t pid = item->pid.real;
1316 : : int ret;
1317 : :
1318 : 359 : pr_info("Collecting tasks starting from %d\n", pid);
1319 : 359 : ret = collect_task(item);
1320 [ + - ]: 359 : if (ret)
1321 : : return -1;
1322 : :
1323 [ + + ]: 552 : list_for_each_entry(child, &item->children, sibling) {
1324 : 193 : ret = collect_subtree(child);
1325 [ + - ]: 193 : if (ret < 0)
1326 : : return -1;
1327 : : }
1328 : :
1329 [ + - ]: 359 : if (check_subtree(item))
1330 : : return -1;
1331 : :
1332 : 359 : return 0;
1333 : : }
1334 : :
1335 : 166 : static int collect_pstree(pid_t pid, const struct cr_options *opts)
1336 : : {
1337 : 166 : int ret, attempts = 5;
1338 : :
1339 : : while (1) {
1340 : 166 : root_item = alloc_pstree_item();
1341 [ + - ]: 166 : if (root_item == NULL)
1342 : : return -1;
1343 : :
1344 : 166 : root_item->pid.real = pid;
1345 : :
1346 : 166 : ret = collect_subtree(root_item);
1347 [ + - ]: 166 : if (ret == 0) {
1348 : : /*
1349 : : * Some tasks could have been reparented to
1350 : : * namespaces' reaper. Check this.
1351 : : */
1352 [ + + ]: 166 : if (opts->namespaces_flags & CLONE_NEWPID)
1353 [ - + ]: 76 : if (check_subtree(root_item))
1354 : : goto try_again;
1355 : :
1356 : : break;
1357 : : }
1358 : :
1359 : : /*
1360 : : * Old tasks can die and new ones can appear while we
1361 : : * try to seize the swarm. It's much simpler (and reliable)
1362 : : * just to restart the collection from the beginning
1363 : : * rather than trying to chase them.
1364 : : */
1365 : : try_again:
1366 [ # # ]: 0 : if (attempts == 0)
1367 : : break;
1368 : :
1369 : 0 : attempts--;
1370 : 0 : pr_info("Trying to suspend tasks again\n");
1371 : :
1372 : 0 : pstree_switch_state(root_item, TASK_ALIVE);
1373 : 166 : free_pstree(root_item);
1374 : : }
1375 : :
1376 : : return ret;
1377 : : }
1378 : :
1379 : 32 : static int dump_task_thread(struct parasite_ctl *parasite_ctl, struct pid *tid)
1380 : : {
1381 : : CoreEntry *core;
1382 : 32 : int ret = -1, fd_core;
1383 : : unsigned int *taddr;
1384 : 32 : pid_t pid = tid->real;
1385 : :
1386 : 32 : pr_info("\n");
1387 : 32 : pr_info("Dumping core for thread (pid: %d)\n", pid);
1388 : 32 : pr_info("----------------------------------------\n");
1389 : :
1390 : 32 : core = core_entry_alloc(1, 0, 0);
1391 [ + - ]: 32 : if (!core)
1392 : : goto err;
1393 : :
1394 : 32 : ret = get_task_regs(pid, core, NULL);
1395 [ + - ]: 32 : if (ret)
1396 : : goto err_free;
1397 : :
1398 : 32 : ret = get_task_futex_robust_list(pid, core->thread_core);
1399 [ + - ]: 32 : if (ret)
1400 : : goto err_free;
1401 : :
1402 : 32 : ret = parasite_dump_thread_seized(parasite_ctl, pid, &taddr,
1403 : 32 : &tid->virt, &core->thread_core->blk_sigset);
1404 [ - + ]: 32 : if (ret) {
1405 : 0 : pr_err("Can't dump thread for pid %d\n", pid);
1406 : 0 : goto err_free;
1407 : : }
1408 : 32 : core->thread_core->has_blk_sigset = true;
1409 : :
1410 : 32 : pr_info("%d: virt_pid=%d tid_address=%p sig_blocked=0x%lx\n", pid,
1411 : : tid->virt, taddr, core->thread_core->blk_sigset);
1412 : 32 : core->thread_info->clear_tid_addr = (u64) taddr;
1413 : :
1414 : 32 : ret = dump_sched_info(pid, core->thread_core);
1415 [ + - ]: 32 : if (ret)
1416 : : goto err_free;
1417 : :
1418 : 32 : fd_core = open_image(CR_FD_CORE, O_DUMP, tid->virt);
1419 [ + - ]: 32 : if (fd_core < 0)
1420 : : goto err_free;
1421 : :
1422 : 32 : ret = pb_write_one(fd_core, core, PB_CORE);
1423 : :
1424 : 32 : close(fd_core);
1425 : : err_free:
1426 : 32 : core_entry_free(core);
1427 : : err:
1428 : 32 : pr_info("----------------------------------------\n");
1429 : 32 : return ret;
1430 : : }
1431 : :
1432 : 10 : static int dump_one_zombie(const struct pstree_item *item,
1433 : : const struct proc_pid_stat *pps)
1434 : : {
1435 : : CoreEntry *core;
1436 : 10 : int ret = -1, fd_core;
1437 : :
1438 : 10 : core = core_entry_alloc(0, 1, 0);
1439 [ + - ]: 10 : if (core == NULL)
1440 : : goto err;
1441 : :
1442 : 10 : core->tc->task_state = TASK_DEAD;
1443 : 10 : core->tc->exit_code = pps->exit_code;
1444 : :
1445 : 10 : fd_core = open_image(CR_FD_CORE, O_DUMP, item->pid.virt);
1446 [ + - ]: 10 : if (fd_core < 0)
1447 : : goto err_free;
1448 : :
1449 : 10 : ret = pb_write_one(fd_core, core, PB_CORE);
1450 : 10 : close(fd_core);
1451 : : err_free:
1452 : 10 : core_entry_free(core);
1453 : : err:
1454 : 10 : return ret;
1455 : : }
1456 : :
1457 : : static struct proc_pid_stat pps_buf;
1458 : :
1459 : 349 : static int dump_task_threads(struct parasite_ctl *parasite_ctl,
1460 : : const struct pstree_item *item)
1461 : : {
1462 : : int i;
1463 : :
1464 [ + + ]: 730 : for (i = 0; i < item->nr_threads; i++) {
1465 : : /* Leader is already dumped */
1466 [ + + ]: 381 : if (item->pid.real == item->threads[i].real) {
1467 : 349 : item->threads[i].virt = item->pid.virt;
1468 : 349 : continue;
1469 : : }
1470 : :
1471 [ + - ]: 32 : if (dump_task_thread(parasite_ctl, &item->threads[i]))
1472 : : return -1;
1473 : : }
1474 : :
1475 : : return 0;
1476 : : }
1477 : :
1478 : 2 : static int fill_zombies_pids(struct pstree_item *item)
1479 : : {
1480 : : struct pstree_item *child;
1481 : : int i, nr;
1482 : : pid_t *ch;
1483 : :
1484 [ + - ]: 2 : if (parse_children(item->pid.virt, &ch, &nr) < 0)
1485 : : return -1;
1486 : :
1487 [ + + ]: 7 : list_for_each_entry(child, &item->children, sibling) {
1488 [ - + ]: 5 : if (child->pid.virt < 0)
1489 : 5 : continue;
1490 [ # # ]: 0 : for (i = 0; i < nr; i++) {
1491 [ # # ]: 0 : if (ch[i] == child->pid.virt) {
1492 : 0 : ch[i] = -1;
1493 : 0 : break;
1494 : : }
1495 : : }
1496 : : }
1497 : :
1498 : 2 : i = 0;
1499 [ + + ]: 7 : list_for_each_entry(child, &item->children, sibling) {
1500 [ + - ]: 5 : if (child->pid.virt > 0)
1501 : 0 : continue;
1502 [ + - ]: 8 : for (; i < nr; i++) {
1503 [ + + ]: 8 : if (ch[i] < 0)
1504 : 3 : continue;
1505 : 5 : child->pid.virt = ch[i];
1506 : 5 : ch[i] = -1;
1507 : 5 : break;
1508 : : }
1509 [ - + ]: 5 : BUG_ON(i == nr);
1510 : : }
1511 : :
1512 : : return 0;
1513 : : }
1514 : :
1515 : 166 : static int dump_zombies()
1516 : : {
1517 : : struct pstree_item *item;
1518 : 166 : int oldfd, ret = -1;
1519 : 166 : int pidns = opts.namespaces_flags & CLONE_NEWPID;
1520 : :
1521 [ + + ]: 166 : if (pidns) {
1522 : 76 : oldfd = set_proc_fd(pidns_proc);
1523 [ + - ]: 76 : if (oldfd < 0)
1524 : : return -1;
1525 : : }
1526 : :
1527 [ + + ]: 525 : for_each_pstree_item(item) {
1528 [ + + ]: 359 : if (item->state != TASK_DEAD)
1529 : 349 : continue;
1530 : :
1531 [ + + ]: 10 : if (item->pid.virt < 0) {
1532 [ + + ]: 7 : if (!pidns)
1533 : 5 : item->pid.virt = item->pid.real;
1534 [ - + ]: 2 : else if (root_item == item) {
1535 : 0 : pr_err("A root task is dead\n");
1536 : 0 : goto err;
1537 [ + - ]: 2 : } else if (fill_zombies_pids(item->parent))
1538 : : goto err;
1539 : : }
1540 : :
1541 : 10 : pr_info("Obtainting zombie stat ... ");
1542 [ + - ]: 10 : if (parse_pid_stat(item->pid.virt, &pps_buf) < 0)
1543 : : goto err;
1544 : :
1545 : 10 : item->sid = pps_buf.sid;
1546 : 10 : item->pgid = pps_buf.pgid;
1547 : :
1548 [ - + ]: 10 : BUG_ON(!list_empty(&item->children));
1549 [ + - ]: 10 : if (dump_one_zombie(item, &pps_buf) < 0)
1550 : : goto err;
1551 : : }
1552 : :
1553 : : ret = 0;
1554 : : err:
1555 [ + + ]: 166 : if (pidns)
1556 : 76 : close_proc();
1557 : :
1558 : 166 : return ret;
1559 : : }
1560 : :
1561 : 359 : static int dump_one_task(struct pstree_item *item)
1562 : : {
1563 : 359 : pid_t pid = item->pid.real;
1564 : 359 : LIST_HEAD(vma_area_list);
1565 : : struct parasite_ctl *parasite_ctl;
1566 : 359 : int ret = -1;
1567 : : struct parasite_dump_misc misc;
1568 : 359 : struct cr_fdset *cr_fdset = NULL;
1569 : : struct parasite_drain_fd *dfds;
1570 : :
1571 : 359 : pr_info("========================================\n");
1572 : 359 : pr_info("Dumping task (pid: %d)\n", pid);
1573 : 359 : pr_info("========================================\n");
1574 : :
1575 [ - + ]: 359 : if (item->state == TASK_STOPPED) {
1576 : 0 : pr_err("Stopped tasks are not supported\n");
1577 : : return -1;
1578 : : }
1579 : :
1580 [ + + ]: 359 : if (item->state == TASK_DEAD)
1581 : : return 0;
1582 : :
1583 [ - + ]: 349 : dfds = xmalloc(sizeof(*dfds));
1584 [ + - ]: 349 : if (!dfds)
1585 : : goto err_free;
1586 : :
1587 : 349 : pr_info("Obtainting task stat ... ");
1588 : 349 : ret = parse_pid_stat(pid, &pps_buf);
1589 [ + - ]: 349 : if (ret < 0)
1590 : : goto err;
1591 : :
1592 : 349 : ret = collect_mappings(pid, &vma_area_list);
1593 [ - + ]: 349 : if (ret) {
1594 : 0 : pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
1595 : 0 : goto err;
1596 : : }
1597 : :
1598 : 349 : ret = collect_fds(pid, dfds);
1599 [ - + ]: 349 : if (ret) {
1600 : 0 : pr_err("Collect fds (pid: %d) failed with %d\n", pid, ret);
1601 : 0 : goto err;
1602 : : }
1603 : :
1604 : 349 : ret = -1;
1605 : 349 : parasite_ctl = parasite_infect_seized(pid, item, &vma_area_list);
1606 [ - + ]: 349 : if (!parasite_ctl) {
1607 : 0 : pr_err("Can't infect (pid: %d) with parasite\n", pid);
1608 : 0 : goto err;
1609 : : }
1610 : :
1611 [ + + ][ + + ]: 349 : if (opts.namespaces_flags & CLONE_NEWPID && root_item == item) {
1612 : 76 : pidns_proc = parasite_get_proc_fd_seized(parasite_ctl);
1613 [ - + ]: 76 : if (pidns_proc < 0) {
1614 : 0 : pr_err("Can't get proc fd (pid: %d)\n", pid);
1615 : 0 : goto err_cure_fdset;
1616 : : }
1617 : : }
1618 : :
1619 : 349 : ret = parasite_dump_misc_seized(parasite_ctl, &misc);
1620 [ - + ]: 349 : if (ret) {
1621 : 0 : pr_err("Can't dump misc (pid: %d)\n", pid);
1622 : 0 : goto err_cure_fdset;
1623 : : }
1624 : :
1625 : 349 : item->pid.virt = misc.pid;
1626 : 349 : item->sid = misc.sid;
1627 : 349 : item->pgid = misc.pgid;
1628 : :
1629 : 349 : pr_info("sid=%d pgid=%d pid=%d\n",
1630 : : item->sid, item->pgid, item->pid.virt);
1631 : :
1632 : 349 : ret = -1;
1633 : 349 : cr_fdset = cr_task_fdset_open(item->pid.virt, O_DUMP);
1634 [ + - ]: 349 : if (!cr_fdset)
1635 : : goto err_cure;
1636 : :
1637 : 349 : ret = dump_task_files_seized(parasite_ctl, cr_fdset, dfds);
1638 [ - + ]: 349 : if (ret) {
1639 : 0 : pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
1640 : 0 : goto err_cure;
1641 : : }
1642 : :
1643 : 349 : ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
1644 [ - + ]: 349 : if (ret) {
1645 : 0 : pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
1646 : 0 : goto err_cure;
1647 : : }
1648 : :
1649 : 349 : ret = parasite_dump_sigacts_seized(parasite_ctl, cr_fdset);
1650 [ - + ]: 349 : if (ret) {
1651 : 0 : pr_err("Can't dump sigactions (pid: %d) with parasite\n", pid);
1652 : 0 : goto err_cure;
1653 : : }
1654 : :
1655 : 349 : ret = parasite_dump_itimers_seized(parasite_ctl, cr_fdset);
1656 [ - + ]: 349 : if (ret) {
1657 : 0 : pr_err("Can't dump itimers (pid: %d)\n", pid);
1658 : 0 : goto err_cure;
1659 : : }
1660 : :
1661 : 349 : ret = dump_task_core_all(pid, &pps_buf, &misc,
1662 : : parasite_ctl, cr_fdset, &vma_area_list);
1663 [ - + ]: 349 : if (ret) {
1664 : 0 : pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
1665 : 0 : goto err_cure;
1666 : : }
1667 : :
1668 : 349 : ret = dump_task_threads(parasite_ctl, item);
1669 [ - + ]: 349 : if (ret) {
1670 : 0 : pr_err("Can't dump threads\n");
1671 : 0 : goto err_cure;
1672 : : }
1673 : :
1674 : 349 : ret = dump_task_creds(parasite_ctl, cr_fdset);
1675 [ - + ]: 349 : if (ret) {
1676 : 0 : pr_err("Dump creds (pid: %d) failed with %d\n", pid, ret);
1677 : 0 : goto err;
1678 : : }
1679 : :
1680 : 349 : ret = parasite_cure_seized(parasite_ctl, item);
1681 [ - + ]: 349 : if (ret) {
1682 : 0 : pr_err("Can't cure (pid: %d) from parasite\n", pid);
1683 : 0 : goto err;
1684 : : }
1685 : :
1686 : 349 : ret = dump_task_mappings(pid, &vma_area_list, cr_fdset);
1687 [ - + ]: 349 : if (ret) {
1688 : 0 : pr_err("Dump mappings (pid: %d) failed with %d\n", pid, ret);
1689 : 0 : goto err;
1690 : : }
1691 : :
1692 : 349 : ret = dump_task_fs(pid, cr_fdset);
1693 [ - + ]: 349 : if (ret) {
1694 : 0 : pr_err("Dump fs (pid: %d) failed with %d\n", pid, ret);
1695 : 0 : goto err;
1696 : : }
1697 : :
1698 : 349 : close_cr_fdset(&cr_fdset);
1699 : : err:
1700 : 349 : close_pid_proc();
1701 : : err_free:
1702 : 349 : free_mappings(&vma_area_list);
1703 [ + - ]: 349 : xfree(dfds);
1704 : : return ret;
1705 : :
1706 : : err_cure:
1707 : 0 : close_cr_fdset(&cr_fdset);
1708 : : err_cure_fdset:
1709 : 0 : parasite_cure_seized(parasite_ctl, item);
1710 : 359 : goto err;
1711 : : }
1712 : :
1713 : 166 : int cr_dump_tasks(pid_t pid, const struct cr_options *opts)
1714 : : {
1715 : : struct pstree_item *item;
1716 : 166 : int ret = -1;
1717 : :
1718 : 166 : pr_info("========================================\n");
1719 : 166 : pr_info("Dumping processes (pid: %d)\n", pid);
1720 : 166 : pr_info("========================================\n");
1721 : :
1722 [ + - ]: 166 : if (cpu_init())
1723 : : goto err;
1724 : :
1725 [ + - ]: 166 : if (network_lock())
1726 : : goto err;
1727 : :
1728 [ + - ]: 166 : if (write_img_inventory())
1729 : : goto err;
1730 : :
1731 [ + - ]: 166 : if (collect_pstree(pid, opts))
1732 : : goto err;
1733 : :
1734 [ + - ]: 166 : if (mntns_collect_root(root_item->pid.real))
1735 : : goto err;
1736 : :
1737 : 166 : ret = collect_sockets(pid);
1738 : :
1739 : : /*
1740 : : * If netns isn't dumped, crtools will fail only
1741 : : * if an unsupported socket will be really dumped.
1742 : : */
1743 [ + - ][ + + ]: 166 : if ((opts->namespaces_flags & CLONE_NEWNET) && ret)
1744 : : goto err;
1745 : :
1746 : 166 : ret = -1;
1747 : :
1748 : 166 : glob_fdset = cr_glob_fdset_open(O_DUMP);
1749 [ + - ]: 166 : if (!glob_fdset)
1750 : : goto err;
1751 : :
1752 [ + + ]: 525 : for_each_pstree_item(item) {
1753 [ + - ]: 359 : if (dump_one_task(item))
1754 : : goto err;
1755 : : }
1756 : :
1757 [ + - ]: 166 : if (dump_verify_tty_sids())
1758 : : goto err;
1759 : :
1760 [ + - ]: 166 : if (dump_zombies())
1761 : : goto err;
1762 : :
1763 [ + - ]: 166 : if (dump_pstree(root_item))
1764 : : goto err;
1765 : :
1766 [ + + ]: 166 : if (opts->namespaces_flags)
1767 [ + - ]: 83 : if (dump_namespaces(&root_item->pid, opts->namespaces_flags) < 0)
1768 : : goto err;
1769 : :
1770 : 166 : ret = cr_dump_shmem();
1771 [ + - ]: 166 : if (ret)
1772 : : goto err;
1773 : :
1774 : 166 : ret = fix_external_unix_sockets();
1775 [ + - ]: 166 : if (ret)
1776 : : goto err;
1777 : :
1778 : 166 : ret = tty_verify_active_pairs();
1779 [ + - ]: 166 : if (ret)
1780 : : goto err;
1781 : :
1782 : 166 : fd_id_show_tree();
1783 : : err:
1784 : 166 : close_cr_fdset(&glob_fdset);
1785 : :
1786 : : /*
1787 : : * If we've failed to do anything -- unlock all TCP sockets
1788 : : * so that the connections can go on. But if we succeeded --
1789 : : * don't, just close them silently.
1790 : : */
1791 [ - + ]: 166 : if (ret)
1792 : 0 : network_unlock();
1793 [ + - ]: 166 : pstree_switch_state(root_item,
1794 : : ret ? TASK_ALIVE : opts->final_state);
1795 : 166 : free_pstree(root_item);
1796 : :
1797 : 166 : close_safe(&pidns_proc);
1798 : :
1799 : 166 : return ret;
1800 : 3844 : }
|