Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <fcntl.h>
3 : : #include <errno.h>
4 : :
5 : : #include <linux/limits.h>
6 : : #include <linux/major.h>
7 : :
8 : : #include <sys/types.h>
9 : : #include <sys/prctl.h>
10 : : #include <sys/mman.h>
11 : : #include <sys/stat.h>
12 : : #include <sys/socket.h>
13 : : #include <sys/un.h>
14 : : #include <stdlib.h>
15 : :
16 : : #include "files.h"
17 : : #include "file-ids.h"
18 : : #include "files-reg.h"
19 : : #include "image.h"
20 : : #include "list.h"
21 : : #include "util.h"
22 : : #include "util-pie.h"
23 : : #include "lock.h"
24 : : #include "sockets.h"
25 : : #include "pstree.h"
26 : : #include "tty.h"
27 : : #include "pipes.h"
28 : : #include "fifo.h"
29 : : #include "eventfd.h"
30 : : #include "eventpoll.h"
31 : : #include "fsnotify.h"
32 : : #include "signalfd.h"
33 : : #include "namespaces.h"
34 : : #include "tun.h"
35 : : #include "fdset.h"
36 : : #include "fs-magic.h"
37 : : #include "proc_parse.h"
38 : :
39 : : #include "parasite.h"
40 : : #include "parasite-syscall.h"
41 : :
42 : : #include "protobuf.h"
43 : : #include "protobuf/fs.pb-c.h"
44 : : #include "protobuf/ext-file.pb-c.h"
45 : :
46 : : #include "plugin.h"
47 : :
48 : : #define FDESC_HASH_SIZE 64
49 : : static struct hlist_head file_desc_hash[FDESC_HASH_SIZE];
50 : :
51 : 1013 : int prepare_shared_fdinfo(void)
52 : : {
53 : : int i;
54 : :
55 [ + + ]: 65845 : for (i = 0; i < FDESC_HASH_SIZE; i++)
56 : 64832 : INIT_HLIST_HEAD(&file_desc_hash[i]);
57 : :
58 : 1013 : return 0;
59 : : }
60 : :
61 : 3733 : int file_desc_add(struct file_desc *d, u32 id, struct file_desc_ops *ops)
62 : : {
63 : 3733 : d->id = id;
64 : 3733 : d->ops = ops;
65 : 3733 : INIT_LIST_HEAD(&d->fd_info_head);
66 : :
67 : 3733 : hlist_add_head(&d->hash, &file_desc_hash[id % FDESC_HASH_SIZE]);
68 : :
69 : 3733 : return 0; /* this is to make tail-calls in collect_one_foo look nice */
70 : : }
71 : :
72 : 16865 : struct file_desc *find_file_desc_raw(int type, u32 id)
73 : : {
74 : : struct file_desc *d;
75 : : struct hlist_head *chain;
76 : :
77 : 16865 : chain = &file_desc_hash[id % FDESC_HASH_SIZE];
78 [ + - ][ + - ]: 16893 : hlist_for_each_entry(d, chain, hash)
[ + - ]
79 [ + + ][ - + ]: 16893 : if (d->ops->type == type && d->id == id)
80 : : return d;
81 : :
82 : : return NULL;
83 : : }
84 : :
85 : : static inline struct file_desc *find_file_desc(FdinfoEntry *fe)
86 : : {
87 : 4278 : return find_file_desc_raw(fe->type, fe->id);
88 : : }
89 : :
90 : : /*
91 : : * A file may be shared between several file descriptors. E.g
92 : : * when doing a fork() every fd of a forker and respective fds
93 : : * of the child have such. Another way of getting shared files
94 : : * is by dup()-ing them or sending them via unix sockets in
95 : : * SCM_RIGHTS message.
96 : : *
97 : : * We restore this type of things in 3 steps (states[] below)
98 : : *
99 : : * 1. Prepare step.
100 : : * Select which task will create the file (open() one, or
101 : : * call any other syscall for than (socket, pipe, etc.). All
102 : : * the others, that share one, create unix sockets under the
103 : : * respective file descriptor (transport socket).
104 : : * 2. Open step.
105 : : * The one who creates the file (the 'master') creates one,
106 : : * then creates one more unix socket (transport) and sends the
107 : : * created file over this socket to the other recepients.
108 : : * 3. Receive step.
109 : : * Those, who wait for the file to appear, receive one via
110 : : * the transport socket, then close the socket and dup() the
111 : : * received file descriptor into its place.
112 : : *
113 : : * There's the 4th step in the states[] array -- the post_open
114 : : * one. This one is not about file-sharing resolving, but about
115 : : * doing something with a file using it's 'desired' fd. The
116 : : * thing is that while going the 3-step process above, the file
117 : : * may appear in variuos places in the task's fd table, and if
118 : : * we want to do something with it's _final_ descriptor value,
119 : : * we should wait for it to appear there. So the post_open is
120 : : * called when the file is finally set into its place.
121 : : */
122 : :
123 : 4659 : struct fdinfo_list_entry *file_master(struct file_desc *d)
124 : : {
125 [ - + ]: 4659 : if (list_empty(&d->fd_info_head)) {
126 : 0 : pr_err("Empty list on file desc id %#x\n", d->id);
127 : 0 : BUG();
128 : : }
129 : :
130 : 4659 : return list_first_entry(&d->fd_info_head,
131 : : struct fdinfo_list_entry, desc_list);
132 : : }
133 : :
134 : 355 : void show_saved_files(void)
135 : : {
136 : : int i;
137 : : struct file_desc *fd;
138 : :
139 : 355 : pr_info("File descs:\n");
140 [ + + ]: 23075 : for (i = 0; i < FDESC_HASH_SIZE; i++)
141 [ + + ][ + + ]: 26343 : hlist_for_each_entry(fd, &file_desc_hash[i], hash) {
[ + + ]
142 : : struct fdinfo_list_entry *le;
143 : :
144 : 3623 : pr_info(" `- type %d ID %#x\n", fd->ops->type, fd->id);
145 [ + + ]: 7901 : list_for_each_entry(le, &fd->fd_info_head, desc_list)
146 : 4278 : pr_info(" `- FD %d pid %d\n", le->fe->fd, le->pid);
147 : : }
148 : 355 : }
149 : :
150 : : /*
151 : : * The gen_id thing is used to optimize the comparison of shared files.
152 : : * If two files have different gen_ids, then they are different for sure.
153 : : * If it matches, we don't know it and have to call sys_kcmp().
154 : : *
155 : : * The kcmp-ids.c engine does this trick, see comments in it for more info.
156 : : */
157 : :
158 : : static u32 make_gen_id(const struct fd_parms *p)
159 : : {
160 : 3839 : return ((u32)p->stat.st_dev) ^ ((u32)p->stat.st_ino) ^ ((u32)p->pos);
161 : : }
162 : :
163 : 3839 : int do_dump_gen_file(struct fd_parms *p, int lfd,
164 : : const struct fdtype_ops *ops, const int fdinfo)
165 : : {
166 : 3839 : FdinfoEntry e = FDINFO_ENTRY__INIT;
167 : : int ret = -1;
168 : :
169 : 3839 : e.type = ops->type;
170 : 3839 : e.id = make_gen_id(p);
171 : 3839 : e.fd = p->fd;
172 : 3839 : e.flags = p->fd_flags;
173 : :
174 : 3839 : ret = fd_id_generate(p->pid, &e, p);
175 [ + + ]: 3839 : if (ret == 1) /* new ID generated */
176 : 2162 : ret = ops->dump(lfd, e.id, p);
177 : :
178 [ + - ]: 3839 : if (ret < 0)
179 : : return ret;
180 : :
181 : 3839 : pr_info("fdinfo: type: 0x%2x flags: %#o/%#o pos: 0x%8"PRIx64" fd: %d\n",
182 : : ops->type, p->flags, (int)p->fd_flags, p->pos, p->fd);
183 : :
184 : 3839 : return pb_write_one(fdinfo, &e, PB_FDINFO);
185 : : }
186 : :
187 : 5068 : int fill_fdlink(int lfd, const struct fd_parms *p, struct fd_link *link)
188 : : {
189 : : int len;
190 : :
191 : 5068 : link->name[0] = '.';
192 : :
193 : 5068 : len = read_fd_link(lfd, &link->name[1], sizeof(link->name) - 1);
194 [ - + ]: 5068 : if (len < 0) {
195 : 0 : pr_err("Can't read link for pid %d fd %d\n", p->pid, p->fd);
196 : 0 : return -1;
197 : : }
198 : :
199 : 5068 : link->len = len + 1;
200 : 5068 : return 0;
201 : : }
202 : :
203 : 3839 : static int fill_fd_params(struct parasite_ctl *ctl, int fd, int lfd,
204 : : struct fd_opts *opts, struct fd_parms *p)
205 : : {
206 : : int ret;
207 : : struct statfs fsbuf;
208 : 3839 : struct fdinfo_common fdinfo = { .mnt_id = -1 };
209 : :
210 [ - + ]: 3839 : if (fstat(lfd, &p->stat) < 0) {
211 : 0 : pr_perror("Can't stat fd %d", lfd);
212 : 0 : return -1;
213 : : }
214 : :
215 [ - + ]: 3839 : if (fstatfs(lfd, &fsbuf) < 0) {
216 : 0 : pr_perror("Can't statfs fd %d", lfd);
217 : 0 : return -1;
218 : : }
219 : :
220 [ + - ]: 3839 : if (parse_fdinfo(lfd, FD_TYPES__UND, NULL, &fdinfo))
221 : : return -1;
222 : :
223 : 3839 : p->fs_type = fsbuf.f_type;
224 : 3839 : p->ctl = ctl;
225 : 3839 : p->fd = fd;
226 : 3839 : p->pos = fdinfo.pos;
227 : 3839 : p->flags = fdinfo.flags;
228 : 3839 : p->mnt_id = fdinfo.mnt_id;
229 : 3839 : p->pid = ctl->pid.real;
230 : 3839 : p->fd_flags = opts->flags;
231 : :
232 : 3839 : fown_entry__init(&p->fown);
233 : :
234 : 3839 : pr_info("%d fdinfo %d: pos: 0x%16"PRIx64" flags: %16o/%#x\n",
235 : : ctl->pid.real, fd, p->pos, p->flags, (int)p->fd_flags);
236 : :
237 : 3839 : ret = fcntl(lfd, F_GETSIG, 0);
238 [ - + ]: 3839 : if (ret < 0) {
239 : 0 : pr_perror("Can't get owner signum on %d", lfd);
240 : 0 : return -1;
241 : : }
242 : 3839 : p->fown.signum = ret;
243 : :
244 [ + + ]: 3839 : if (opts->fown.pid == 0)
245 : : return 0;
246 : :
247 : 8 : p->fown.pid = opts->fown.pid;
248 : 8 : p->fown.pid_type = opts->fown.pid_type;
249 : 8 : p->fown.uid = opts->fown.uid;
250 : 8 : p->fown.euid = opts->fown.euid;
251 : :
252 : 8 : return 0;
253 : : }
254 : :
255 : : static const struct fdtype_ops *get_misc_dev_ops(int minor)
256 : : {
257 [ # # ]: 0 : switch (minor) {
258 : : case TUN_MINOR:
259 : : return &tunfile_dump_ops;
260 : : };
261 : :
262 : : return NULL;
263 : : }
264 : :
265 : 965 : static int dump_chrdev(struct fd_parms *p, int lfd, const int fdinfo)
266 : : {
267 : 1930 : int maj = major(p->stat.st_rdev);
268 : : const struct fdtype_ops *ops;
269 : :
270 [ + - + + ]: 965 : switch (maj) {
271 : : case MEM_MAJOR:
272 : : ops = ®file_dump_ops;
273 : : break;
274 : : case TTYAUX_MAJOR:
275 : : case UNIX98_PTY_MASTER_MAJOR ... (UNIX98_PTY_MASTER_MAJOR + UNIX98_PTY_MAJOR_COUNT - 1):
276 : : case UNIX98_PTY_SLAVE_MAJOR:
277 : : ops = &tty_dump_ops;
278 : 54 : break;
279 : : case MISC_MAJOR:
280 : 0 : ops = get_misc_dev_ops(minor(p->stat.st_rdev));
281 [ # # ]: 0 : if (ops)
282 : : break;
283 : : /* fallthrough */
284 : : default: {
285 : : char more[32];
286 : :
287 : : sprintf(more, "%d:%d", maj, minor(p->stat.st_rdev));
288 : 4 : return dump_unsupp_fd(p, lfd, fdinfo, "chr", more);
289 : : }
290 : : }
291 : :
292 : 961 : return do_dump_gen_file(p, lfd, ops, fdinfo);
293 : : }
294 : :
295 : 3839 : static int dump_one_file(struct parasite_ctl *ctl, int fd, int lfd, struct fd_opts *opts,
296 : : const int fdinfo)
297 : : {
298 : 3839 : struct fd_parms p = FD_PARMS_INIT;
299 : : const struct fdtype_ops *ops;
300 : :
301 [ - + ]: 3839 : if (fill_fd_params(ctl, fd, lfd, opts, &p) < 0) {
302 : 0 : pr_perror("Can't get stat on %d", fd);
303 : 0 : return -1;
304 : : }
305 : :
306 [ + + ]: 3839 : if (S_ISSOCK(p.stat.st_mode))
307 : 228 : return dump_socket(&p, lfd, fdinfo);
308 : :
309 [ + + ]: 3611 : if (S_ISCHR(p.stat.st_mode))
310 : 965 : return dump_chrdev(&p, lfd, fdinfo);
311 : :
312 [ + + ]: 2646 : if (p.fs_type == ANON_INODE_FS_MAGIC) {
313 : : char link[32];
314 : :
315 [ + - ]: 20 : if (read_fd_link(lfd, link, sizeof(link)) < 0)
316 : : return -1;
317 : :
318 [ + + ]: 20 : if (is_eventfd_link(link))
319 : : ops = &eventfd_dump_ops;
320 [ + + ]: 16 : else if (is_eventpoll_link(link))
321 : : ops = &eventpoll_dump_ops;
322 [ + + ]: 12 : else if (is_inotify_link(link))
323 : : ops = &inotify_dump_ops;
324 [ + + ]: 8 : else if (is_fanotify_link(link))
325 : : ops = &fanotify_dump_ops;
326 [ - + ]: 4 : else if (is_signalfd_link(link))
327 : : ops = &signalfd_dump_ops;
328 : : else
329 : 0 : return dump_unsupp_fd(&p, lfd, fdinfo, "anon", link);
330 : :
331 : 20 : return do_dump_gen_file(&p, lfd, ops, fdinfo);
332 : : }
333 : :
334 [ + + ]: 2626 : if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode)) {
335 : : struct fd_link link;
336 : :
337 [ + - ]: 2028 : if (fill_fdlink(lfd, &p, &link))
338 : : return -1;
339 : :
340 : 2028 : p.link = &link;
341 [ + + ]: 2028 : if (link.name[1] == '/')
342 : 2024 : return do_dump_gen_file(&p, lfd, ®file_dump_ops, fdinfo);
343 : :
344 [ + - ]: 4 : if (check_ns_proc(&link))
345 : 4 : return do_dump_gen_file(&p, lfd, &nsfile_dump_ops, fdinfo);
346 : :
347 : 2028 : return dump_unsupp_fd(&p, lfd, fdinfo, "reg", link.name + 1);
348 : : }
349 : :
350 [ + - ]: 598 : if (S_ISFIFO(p.stat.st_mode)) {
351 [ + + ]: 598 : if (p.fs_type == PIPEFS_MAGIC)
352 : : ops = &pipe_dump_ops;
353 : : else
354 : : ops = &fifo_dump_ops;
355 : :
356 : 598 : return do_dump_gen_file(&p, lfd, ops, fdinfo);
357 : : }
358 : :
359 : 0 : return dump_unsupp_fd(&p, lfd, fdinfo, "unknown", NULL);
360 : : }
361 : :
362 : 907 : int dump_task_files_seized(struct parasite_ctl *ctl, struct pstree_item *item,
363 : : struct parasite_drain_fd *dfds)
364 : : {
365 : : int *lfds, fdinfo;
366 : : struct fd_opts *opts;
367 : : int i, ret = -1;
368 : :
369 : 907 : pr_info("\n");
370 : 907 : pr_info("Dumping opened files (pid: %d)\n", ctl->pid.real);
371 : 907 : pr_info("----------------------------------------\n");
372 : :
373 [ - + ]: 907 : lfds = xmalloc(dfds->nr_fds * sizeof(int));
374 [ + - ]: 907 : if (!lfds)
375 : : goto err;
376 : :
377 [ - + ]: 907 : opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts));
378 [ + - ]: 907 : if (!opts)
379 : : goto err1;
380 : :
381 : 907 : ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts);
382 [ + - ]: 907 : if (ret)
383 : : goto err2;
384 : :
385 : 907 : fdinfo = open_image(CR_FD_FDINFO, O_DUMP, item->ids->files_id);
386 [ + - ]: 907 : if (fdinfo < 0)
387 : : goto err2;
388 : :
389 [ + + ]: 4746 : for (i = 0; i < dfds->nr_fds; i++) {
390 : 3839 : ret = dump_one_file(ctl, dfds->fds[i], lfds[i], opts + i, fdinfo);
391 : 3839 : close(lfds[i]);
392 [ + - ]: 3839 : if (ret)
393 : : break;
394 : : }
395 : :
396 : 907 : close(fdinfo);
397 : :
398 : 907 : pr_info("----------------------------------------\n");
399 : : err2:
400 [ + - ]: 907 : xfree(opts);
401 : : err1:
402 [ + - ]: 907 : xfree(lfds);
403 : : err:
404 : 907 : return ret;
405 : : }
406 : :
407 : 17055 : static int predump_one_fd(int pid, int fd)
408 : : {
409 : : const struct fdtype_ops *ops;
410 : : char link[PATH_MAX], t[32];
411 : : int ret = 0;
412 : :
413 : : snprintf(t, sizeof(t), "/proc/%d/fd/%d", pid, fd);
414 : 17055 : ret = readlink(t, link, sizeof(link));
415 [ - + ]: 17055 : if (ret < 0) {
416 : 0 : pr_perror("Can't read link of fd %d", fd);
417 : 0 : return -1;
418 [ - + ]: 17055 : } else if ((size_t)ret == sizeof(link)) {
419 : 0 : pr_err("Buffer for read link of fd %d is too small\n", fd);
420 : 0 : return -1;
421 : : }
422 : 17055 : link[ret] = 0;
423 : :
424 : : ret = 0;
425 [ + + ]: 17055 : if (is_inotify_link(link))
426 : : ops = &inotify_dump_ops;
427 [ + + ]: 17043 : else if (is_fanotify_link(link))
428 : : ops = &fanotify_dump_ops;
429 : : else
430 : : goto out;
431 : :
432 : 24 : pr_debug("Pre-dumping %d's %d fd\n", pid, fd);
433 : 24 : ret = ops->pre_dump(pid, fd);
434 : : out:
435 : 17055 : return ret;
436 : : }
437 : :
438 : 2745 : int predump_task_files(int pid)
439 : : {
440 : : struct dirent *de;
441 : : DIR *fd_dir;
442 : : int ret = -1;
443 : :
444 : 2745 : pr_info("Pre-dump fds for %d)\n", pid);
445 : :
446 [ - + ][ + - ]: 2745 : fd_dir = opendir_proc(pid, "fd");
[ - + ]
447 [ + - ]: 2745 : if (!fd_dir)
448 : : return -1;
449 : :
450 [ + + ]: 25290 : while ((de = readdir(fd_dir))) {
451 [ + + ]: 22545 : if (dir_dots(de))
452 : 5490 : continue;
453 : :
454 [ + - ]: 22545 : if (predump_one_fd(pid, atoi(de->d_name)))
455 : : goto out;
456 : : }
457 : :
458 : : ret = 0;
459 : : out:
460 : 2745 : closedir(fd_dir);
461 : 2745 : return ret;
462 : : }
463 : :
464 : 7200 : int restore_fown(int fd, FownEntry *fown)
465 : : {
466 : : struct f_owner_ex owner;
467 : : uid_t uids[3];
468 : 7200 : pid_t pid = getpid();
469 : :
470 [ + + ]: 7200 : if (fown->signum) {
471 [ - + ]: 4 : if (fcntl(fd, F_SETSIG, fown->signum)) {
472 : 0 : pr_perror("%d: Can't set signal", pid);
473 : 0 : return -1;
474 : : }
475 : : }
476 : :
477 : : /* May be untouched */
478 [ + + ]: 7200 : if (!fown->pid)
479 : : return 0;
480 : :
481 [ - + ]: 4 : if (getresuid(&uids[0], &uids[1], &uids[2])) {
482 : 0 : pr_perror("%d: Can't get current UIDs", pid);
483 : 0 : return -1;
484 : : }
485 : :
486 [ - + ]: 4 : if (setresuid(fown->uid, fown->euid, uids[2])) {
487 : 0 : pr_perror("%d: Can't set UIDs", pid);
488 : 0 : return -1;
489 : : }
490 : :
491 : 4 : owner.type = fown->pid_type;
492 : 4 : owner.pid = fown->pid;
493 : :
494 [ - + ]: 4 : if (fcntl(fd, F_SETOWN_EX, &owner)) {
495 : 0 : pr_perror("%d: Can't setup %d file owner pid",
496 : : pid, fd);
497 : 0 : return -1;
498 : : }
499 : :
500 [ - + ]: 4 : if (setresuid(uids[0], uids[1], uids[2])) {
501 : 0 : pr_perror("%d: Can't revert UIDs back", pid);
502 : 0 : return -1;
503 : : }
504 : :
505 : : return 0;
506 : : }
507 : :
508 : 316 : int rst_file_params(int fd, FownEntry *fown, int flags)
509 : : {
510 [ + - ]: 316 : if (set_fd_flags(fd, flags) < 0)
511 : : return -1;
512 [ + - ]: 316 : if (restore_fown(fd, fown) < 0)
513 : : return -1;
514 : 316 : return 0;
515 : : }
516 : :
517 : 4278 : static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
518 : : {
519 : : struct fdinfo_list_entry *le, *new_le;
520 : : struct file_desc *fdesc;
521 : :
522 : 4278 : pr_info("Collect fdinfo pid=%d fd=%d id=%#x\n",
523 : : pid, e->fd, e->id);
524 : :
525 : 4278 : new_le = shmalloc(sizeof(*new_le));
526 [ + - ]: 4278 : if (!new_le)
527 : : return -1;
528 : :
529 : : futex_init(&new_le->real_pid);
530 : 4278 : new_le->pid = pid;
531 : 4278 : new_le->fe = e;
532 : :
533 : : fdesc = find_file_desc(e);
534 [ - + ]: 4278 : if (fdesc == NULL) {
535 : 0 : pr_err("No file for fd %d id %#x\n", e->fd, e->id);
536 : 0 : return -1;
537 : : }
538 : :
539 [ + + ]: 8853 : list_for_each_entry(le, &fdesc->fd_info_head, desc_list)
540 [ + + ]: 5911 : if (pid_rst_prio(new_le->pid, le->pid))
541 : : break;
542 : :
543 [ + + ]: 4278 : if (fdesc->ops->collect_fd)
544 : 3416 : fdesc->ops->collect_fd(fdesc, new_le, rst_info);
545 : : else
546 : : collect_gen_fd(new_le, rst_info);
547 : :
548 : 4278 : list_add_tail(&new_le->desc_list, &le->desc_list);
549 : 4278 : new_le->desc = fdesc;
550 : :
551 : 4278 : return 0;
552 : : }
553 : :
554 : 12 : int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id)
555 : : {
556 : : FdinfoEntry *e;
557 : :
558 [ + - ]: 12 : if (!ctl_tty_id)
559 : : return 0;
560 : :
561 : 12 : pr_info("Requesting for ctl tty %#x into service fd\n", ctl_tty_id);
562 : :
563 [ - + ]: 12 : e = xmalloc(sizeof(*e));
564 [ + - ]: 12 : if (!e)
565 : : return -1;
566 : :
567 : 12 : fdinfo_entry__init(e);
568 : :
569 : 12 : e->id = ctl_tty_id;
570 : 12 : e->fd = reserve_service_fd(CTL_TTY_OFF);
571 : 12 : e->type = FD_TYPES__TTY;
572 : :
573 [ - + ]: 12 : if (collect_fd(pid, e, rst_info)) {
574 [ # # ]: 0 : xfree(e);
575 : : return -1;
576 : : }
577 : :
578 : : return 0;
579 : : }
580 : :
581 : 1011 : int prepare_fd_pid(struct pstree_item *item)
582 : : {
583 : : int fdinfo_fd, ret = 0;
584 : 1011 : pid_t pid = item->pid.virt;
585 : 1011 : struct rst_info *rst_info = item->rst;
586 : :
587 : : INIT_LIST_HEAD(&rst_info->fds);
588 : 1011 : INIT_LIST_HEAD(&rst_info->eventpoll);
589 : 1011 : INIT_LIST_HEAD(&rst_info->tty_slaves);
590 : :
591 [ - + ]: 1011 : if (!fdinfo_per_id) {
592 : 0 : fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR | O_OPT, pid);
593 [ # # ]: 954 : if (fdinfo_fd < 0) {
594 [ # # ]: 0 : if (fdinfo_fd == -ENOENT)
595 : : return 0;
596 : 0 : return -1;
597 : : }
598 : : } else {
599 [ + + ]: 1011 : if (item->ids == NULL) /* zombie */
600 : : return 0;
601 : :
602 [ + + ][ + + ]: 981 : if (item->rst->fdt && item->rst->fdt->pid != item->pid.virt)
603 : : return 0;
604 : :
605 : 954 : fdinfo_fd = open_image(CR_FD_FDINFO, O_RSTR, item->ids->files_id);
606 [ + - ]: 954 : if (fdinfo_fd < 0)
607 : : return -1;
608 : : }
609 : :
610 : : while (1) {
611 : : FdinfoEntry *e;
612 : :
613 : 5220 : ret = pb_read_one_eof(fdinfo_fd, &e, PB_FDINFO);
614 [ + + ]: 5220 : if (ret <= 0)
615 : : break;
616 : :
617 : 4266 : ret = collect_fd(pid, e, rst_info);
618 [ - + ]: 4266 : if (ret < 0) {
619 : 0 : fdinfo_entry__free_unpacked(e, NULL);
620 : 0 : break;
621 : : }
622 : 4266 : }
623 : :
624 : 954 : close(fdinfo_fd);
625 : 954 : return ret;
626 : : }
627 : :
628 : : #define SETFL_MASK (O_APPEND | O_ASYNC | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
629 : 316 : int set_fd_flags(int fd, int flags)
630 : : {
631 : : int ret;
632 : :
633 : 316 : ret = fcntl(fd, F_GETFL, 0);
634 [ + - ]: 316 : if (ret < 0)
635 : : goto err;
636 : :
637 : 316 : flags = (SETFL_MASK & flags) | (ret & ~SETFL_MASK);
638 : :
639 : 316 : ret = fcntl(fd, F_SETFL, flags);
640 [ - + ]: 316 : if (ret < 0)
641 : : goto err;
642 : : return 0;
643 : :
644 : : err:
645 : 0 : pr_perror("fcntl call on fd %d (flags %x) failed", fd, flags);
646 : 0 : return -1;
647 : : }
648 : :
649 : : struct fd_open_state {
650 : : char *name;
651 : : int (*cb)(int, struct fdinfo_list_entry *);
652 : :
653 : : /*
654 : : * Two last stages -- receive fds and post-open them -- are
655 : : * not required always. E.g. if no fd sharing takes place
656 : : * or task doens't have any files that need to be post-opened.
657 : : *
658 : : * Thus, in order not to scan through fdinfo-s lists in vain
659 : : * and speed things up a little bit, we may want to skeep these.
660 : : */
661 : : bool required;
662 : : };
663 : :
664 : : static int open_transport_fd(int pid, struct fdinfo_list_entry *fle);
665 : : static int open_fd(int pid, struct fdinfo_list_entry *fle);
666 : : static int receive_fd(int pid, struct fdinfo_list_entry *fle);
667 : : static int post_open_fd(int pid, struct fdinfo_list_entry *fle);
668 : :
669 : : static struct fd_open_state states[] = {
670 : : { "prepare", open_transport_fd, true,},
671 : : { "create", open_fd, true,},
672 : : { "receive", receive_fd, false,},
673 : : { "post_create", post_open_fd, false,},
674 : : };
675 : :
676 : : #define want_recv_stage() do { states[2].required = true; } while (0)
677 : : #define want_post_open_stage() do { states[3].required = true; } while (0)
678 : :
679 : 1074 : static void transport_name_gen(struct sockaddr_un *addr, int *len,
680 : : int pid, int fd)
681 : : {
682 : 1074 : addr->sun_family = AF_UNIX;
683 : 1074 : snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%d", pid, fd);
684 : 1074 : *len = SUN_LEN(addr);
685 : 1074 : *addr->sun_path = '\0';
686 : 1074 : }
687 : :
688 : : static int should_open_transport(FdinfoEntry *fe, struct file_desc *fd)
689 : : {
690 [ + + ]: 894 : if (fd->ops->want_transport)
691 : 228 : return fd->ops->want_transport(fe, fd);
692 : : else
693 : : return 0;
694 : : }
695 : :
696 : 1577 : static int open_transport_fd(int pid, struct fdinfo_list_entry *fle)
697 : : {
698 : : struct fdinfo_list_entry *flem;
699 : : struct sockaddr_un saddr;
700 : : int sock;
701 : : int ret, sun_len;
702 : :
703 : 1577 : flem = file_master(fle->desc);
704 : :
705 [ + + ]: 1577 : if (flem->pid == pid) {
706 [ + + ]: 1144 : if (flem->fe->fd != fle->fe->fd)
707 : : /* dup-ed file. Will be opened in the open_fd */
708 : : return 0;
709 : :
710 [ + + ]: 894 : if (!should_open_transport(fle->fe, fle->desc))
711 : : /* pure master file */
712 : : return 0;
713 : :
714 : : /*
715 : : * some master file, that wants a transport, e.g.
716 : : * a pipe or unix socket pair 'slave' end
717 : : */
718 : : }
719 : :
720 : 527 : transport_name_gen(&saddr, &sun_len, getpid(), fle->fe->fd);
721 : :
722 : 527 : pr_info("\t\tCreate transport fd %s\n", saddr.sun_path + 1);
723 : :
724 : :
725 : 527 : sock = socket(PF_UNIX, SOCK_DGRAM, 0);
726 [ - + ]: 527 : if (sock < 0) {
727 : 0 : pr_perror("Can't create socket");
728 : 0 : return -1;
729 : : }
730 : 527 : ret = bind(sock, &saddr, sun_len);
731 [ - + ]: 527 : if (ret < 0) {
732 : 0 : pr_perror("Can't bind unix socket %s", saddr.sun_path + 1);
733 : 0 : return -1;
734 : : }
735 : :
736 : 527 : ret = reopen_fd_as(fle->fe->fd, sock);
737 [ + - ]: 527 : if (ret < 0)
738 : : return -1;
739 : :
740 : 527 : pr_info("\t\tWake up fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
741 : 527 : futex_set_and_wake(&fle->real_pid, getpid());
742 : 527 : want_recv_stage();
743 : :
744 : 527 : return 0;
745 : : }
746 : :
747 : 547 : int send_fd_to_peer(int fd, struct fdinfo_list_entry *fle, int sock)
748 : : {
749 : : struct sockaddr_un saddr;
750 : : int len;
751 : :
752 : 547 : pr_info("\t\tWait fdinfo pid=%d fd=%d\n", fle->pid, fle->fe->fd);
753 : 547 : futex_wait_while(&fle->real_pid, 0);
754 : 547 : transport_name_gen(&saddr, &len,
755 : 547 : futex_get(&fle->real_pid), fle->fe->fd);
756 : 547 : pr_info("\t\tSend fd %d to %s\n", fd, saddr.sun_path + 1);
757 : 1094 : return send_fd(sock, &saddr, len, fd);
758 : : }
759 : :
760 : 2288 : static int send_fd_to_self(int fd, struct fdinfo_list_entry *fle, int *sock)
761 : : {
762 : 1144 : int dfd = fle->fe->fd;
763 : :
764 [ + + ]: 1144 : if (fd == dfd)
765 : : return 0;
766 : :
767 : 250 : pr_info("\t\t\tGoing to dup %d into %d\n", fd, dfd);
768 [ + - ]: 250 : if (move_img_fd(sock, dfd))
769 : : return -1;
770 : :
771 [ - + ]: 250 : if (dup2(fd, dfd) != dfd) {
772 : 0 : pr_perror("Can't dup local fd %d -> %d", fd, dfd);
773 : : return -1;
774 : : }
775 : :
776 [ - + ]: 250 : if (fcntl(dfd, F_SETFD, fle->fe->flags) == -1) {
777 : 0 : pr_perror("Unable to set file descriptor flags");
778 : : return -1;
779 : : }
780 : :
781 : : return 0;
782 : : }
783 : :
784 : 374 : static int post_open_fd(int pid, struct fdinfo_list_entry *fle)
785 : : {
786 : 374 : struct file_desc *d = fle->desc;
787 : :
788 [ + + ]: 374 : if (!d->ops->post_open)
789 : : return 0;
790 : :
791 [ + + ]: 160 : if (is_service_fd(fle->fe->fd, CTL_TTY_OFF))
792 : 8 : return d->ops->post_open(d, fle->fe->fd);
793 : :
794 [ + + ]: 152 : if (fle != file_master(d))
795 : : return 0;
796 : :
797 : 148 : return d->ops->post_open(d, fle->fe->fd);
798 : : }
799 : :
800 : :
801 : 894 : static int serve_out_fd(int pid, int fd, struct file_desc *d)
802 : : {
803 : : int sock, ret;
804 : : struct fdinfo_list_entry *fle;
805 : :
806 : 894 : sock = socket(PF_UNIX, SOCK_DGRAM, 0);
807 [ - + ]: 894 : if (sock < 0) {
808 : 0 : pr_perror("Can't create socket");
809 : 0 : return -1;
810 : : }
811 : :
812 : 894 : pr_info("\t\tCreate fd for %d\n", fd);
813 : :
814 [ + + ]: 2483 : list_for_each_entry(fle, &d->fd_info_head, desc_list) {
815 [ + + ]: 1589 : if (pid == fle->pid)
816 : 1144 : ret = send_fd_to_self(fd, fle, &sock);
817 : : else
818 : 445 : ret = send_fd_to_peer(fd, fle, sock);
819 : :
820 [ - + ]: 1589 : if (ret) {
821 : 0 : pr_err("Can't sent fd %d to %d\n", fd, fle->pid);
822 : 0 : return -1;
823 : : }
824 : : }
825 : :
826 : 894 : close(sock);
827 : 894 : return 0;
828 : : }
829 : :
830 : 1577 : static int open_fd(int pid, struct fdinfo_list_entry *fle)
831 : : {
832 : 1577 : struct file_desc *d = fle->desc;
833 : : int new_fd;
834 : :
835 [ + + ]: 1577 : if (d->ops->post_open)
836 : 160 : want_post_open_stage();
837 : :
838 [ + + ]: 1577 : if (fle != file_master(d))
839 : : return 0;
840 : :
841 : 894 : new_fd = d->ops->open(d);
842 [ + - ]: 894 : if (new_fd < 0)
843 : : return -1;
844 : :
845 [ + - ]: 894 : if (reopen_fd_as(fle->fe->fd, new_fd))
846 : : return -1;
847 : :
848 [ - + ]: 894 : if (fcntl(fle->fe->fd, F_SETFD, fle->fe->flags) == -1) {
849 : 0 : pr_perror("Unable to set file descriptor flags");
850 : 0 : return -1;
851 : : }
852 : :
853 : 894 : return serve_out_fd(pid, fle->fe->fd, d);
854 : : }
855 : :
856 : 767 : static int receive_fd(int pid, struct fdinfo_list_entry *fle)
857 : : {
858 : : int tmp;
859 : : struct fdinfo_list_entry *flem;
860 : :
861 : 767 : flem = file_master(fle->desc);
862 [ + + ]: 767 : if (flem->pid == pid)
863 : : return 0;
864 : :
865 : 433 : pr_info("\tReceive fd for %d\n", fle->fe->fd);
866 : :
867 : 433 : tmp = recv_fd(fle->fe->fd);
868 [ - + ]: 433 : if (tmp < 0) {
869 : 0 : pr_err("Can't get fd %d\n", tmp);
870 : 0 : return -1;
871 : : }
872 : 433 : close(fle->fe->fd);
873 : :
874 [ + - ]: 433 : if (reopen_fd_as(fle->fe->fd, tmp) < 0)
875 : : return -1;
876 : :
877 [ - + ]: 433 : if (fcntl(fle->fe->fd, F_SETFD, fle->fe->flags) == -1) {
878 : 0 : pr_perror("Unable to set file descriptor flags");
879 : 0 : return -1;
880 : : }
881 : :
882 : : return 0;
883 : : }
884 : :
885 : 4295 : static int open_fdinfo(int pid, struct fdinfo_list_entry *fle, int state)
886 : : {
887 : 4295 : pr_info("\tRestoring fd %d (state -> %s)\n",
888 : : fle->fe->fd, states[state].name);
889 : 4295 : return states[state].cb(pid, fle);
890 : : }
891 : :
892 : 2691 : static int open_fdinfos(int pid, struct list_head *list, int state)
893 : : {
894 : : int ret = 0;
895 : : struct fdinfo_list_entry *fle;
896 : :
897 [ + + ]: 6986 : list_for_each_entry(fle, list, ps_list) {
898 : 4295 : ret = open_fdinfo(pid, fle, state);
899 [ + - ]: 4295 : if (ret)
900 : : break;
901 : : }
902 : :
903 : 2691 : return ret;
904 : : }
905 : :
906 : 826 : int close_old_fds(struct pstree_item *me)
907 : : {
908 : : DIR *dir;
909 : : struct dirent *de;
910 : : int fd, ret;
911 : :
912 [ - + ][ + - ]: 826 : dir = opendir_proc(getpid(), "fd");
[ - + ]
913 [ + - ]: 826 : if (dir == NULL)
914 : : return -1;
915 : :
916 [ + + ]: 9345 : while ((de = readdir(dir))) {
917 [ + + ]: 8519 : if (dir_dots(de))
918 : 1652 : continue;
919 : :
920 : 6867 : ret = sscanf(de->d_name, "%d", &fd);
921 [ - + ]: 6867 : if (ret != 1) {
922 : 0 : pr_err("Can't parse %s\n", de->d_name);
923 : 0 : return -1;
924 : : }
925 : :
926 [ + + ][ + + ]: 6867 : if ((!is_any_service_fd(fd)) && (dirfd(dir) != fd))
927 : 8519 : close_safe(&fd);
928 : : }
929 : :
930 : 826 : closedir(dir);
931 : 826 : close_pid_proc();
932 : :
933 : 826 : return 0;
934 : : }
935 : :
936 : 348 : int prepare_fds(struct pstree_item *me)
937 : : {
938 : : u32 ret = 0;
939 : : int state;
940 : :
941 : 348 : pr_info("Opening fdinfo-s\n");
942 : :
943 [ + + ]: 348 : if (me->rst->fdt) {
944 : : struct fdt *fdt = me->rst->fdt;
945 : :
946 : : /*
947 : : * Wait all tasks, who share a current fd table.
948 : : * We should be sure, that nobody use any file
949 : : * descriptor while fdtable is being restored.
950 : : */
951 : 7 : futex_inc_and_wake(&fdt->fdt_lock);
952 : 7 : futex_wait_while_lt(&fdt->fdt_lock, fdt->nr);
953 : :
954 [ + + ]: 348 : if (fdt->pid != me->pid.virt) {
955 : 5 : pr_info("File descriptor table is shared with %d\n", fdt->pid);
956 : 5 : futex_wait_until(&fdt->fdt_lock, fdt->nr + 1);
957 : 5 : goto out;
958 : : }
959 : : }
960 : :
961 [ + + ]: 1715 : for (state = 0; state < ARRAY_SIZE(states); state++) {
962 [ + + ]: 1372 : if (!states[state].required) {
963 : 475 : pr_debug("Skipping %s fd stage\n", states[state].name);
964 : 475 : continue;
965 : : }
966 : :
967 : 897 : ret = open_fdinfos(me->pid.virt, &me->rst->fds, state);
968 [ + - ]: 897 : if (ret)
969 : : break;
970 : :
971 : : /*
972 : : * Now handle TTYs. Slaves are delayed to be sure masters
973 : : * are already opened.
974 : : */
975 : 897 : ret = open_fdinfos(me->pid.virt, &me->rst->tty_slaves, state);
976 [ + - ]: 897 : if (ret)
977 : : break;
978 : :
979 : : /*
980 : : * The eventpoll descriptors require all the other ones
981 : : * to be already restored, thus we store them in a separate
982 : : * list and restore at the very end.
983 : : */
984 : 897 : ret = open_fdinfos(me->pid.virt, &me->rst->eventpoll, state);
985 [ + - ]: 897 : if (ret)
986 : : break;
987 : : }
988 : :
989 [ + + ]: 343 : if (me->rst->fdt)
990 : 2 : futex_inc_and_wake(&me->rst->fdt->fdt_lock);
991 : : out:
992 : 348 : close_service_fd(CR_PROC_FD_OFF);
993 : 348 : tty_fini_fds();
994 : 348 : return ret;
995 : : }
996 : :
997 : 348 : static int fchroot(int fd)
998 : : {
999 : : char fd_path[PSFDS];
1000 : :
1001 : : /*
1002 : : * There's no such thing in syscalls. We can emulate
1003 : : * it using the /proc/self/fd/ :)
1004 : : */
1005 : :
1006 : : sprintf(fd_path, "/proc/self/fd/%d", fd);
1007 : 348 : pr_debug("Going to chroot into %s\n", fd_path);
1008 : 348 : return chroot(fd_path);
1009 : : }
1010 : :
1011 : 348 : int prepare_fs(int pid)
1012 : : {
1013 : : int ifd, dd, ret = -1;
1014 : : FsEntry *fe;
1015 : :
1016 : 348 : ifd = open_image(CR_FD_FS, O_RSTR, pid);
1017 [ + - ]: 348 : if (ifd < 0)
1018 : : goto out;
1019 : :
1020 [ + - ]: 348 : if (pb_read_one(ifd, &fe, PB_FS) < 0)
1021 : : goto out_i;
1022 : :
1023 : : /*
1024 : : * Restore CWD
1025 : : */
1026 : :
1027 : 348 : dd = open_reg_by_id(fe->cwd_id);
1028 [ - + ]: 348 : if (dd < 0) {
1029 : 0 : pr_err("Can't open cwd %#x\n", fe->cwd_id);
1030 : 0 : goto err;
1031 : : }
1032 : :
1033 : 348 : ret = fchdir(dd);
1034 : 348 : close(dd);
1035 [ - + ]: 348 : if (ret < 0) {
1036 : 0 : pr_perror("Can't change cwd");
1037 : 0 : goto err;
1038 : : }
1039 : :
1040 : : /*
1041 : : * Restore root
1042 : : */
1043 : :
1044 : 348 : dd = open_reg_by_id(fe->root_id);
1045 [ - + ]: 348 : if (dd < 0) {
1046 : 0 : pr_err("Can't open root %#x\n", fe->root_id);
1047 : 0 : goto err;
1048 : : }
1049 : :
1050 : 348 : ret = fchroot(dd);
1051 : 348 : close(dd);
1052 [ - + ]: 348 : if (ret < 0) {
1053 : 0 : pr_perror("Can't change root");
1054 : 0 : goto err;
1055 : : }
1056 : :
1057 [ + - ]: 348 : if (fe->has_umask) {
1058 : 348 : pr_info("Restoring umask to %o\n", fe->umask);
1059 : 348 : umask(fe->umask);
1060 : : }
1061 : :
1062 : : ret = 0;
1063 : : err:
1064 : 348 : fs_entry__free_unpacked(fe, NULL);
1065 : : out_i:
1066 : 348 : close_safe(&ifd);
1067 : : out:
1068 : 348 : return ret;
1069 : : }
1070 : :
1071 : 45 : int shared_fdt_prepare(struct pstree_item *item)
1072 : : {
1073 : 45 : struct pstree_item *parent = item->parent;
1074 : : struct fdt *fdt;
1075 : :
1076 [ + + ]: 45 : if (!parent->rst->fdt) {
1077 : 15 : fdt = shmalloc(sizeof(*item->rst->fdt));
1078 [ + - ]: 15 : if (fdt == NULL)
1079 : : return -1;
1080 : :
1081 : 15 : parent->rst->fdt = fdt;
1082 : :
1083 : : futex_init(&fdt->fdt_lock);
1084 : 15 : fdt->nr = 1;
1085 : 15 : fdt->pid = parent->pid.virt;
1086 : : } else
1087 : : fdt = parent->rst->fdt;
1088 : :
1089 : 45 : item->rst->fdt = fdt;
1090 : 45 : item->rst->service_fd_id = fdt->nr;
1091 : 45 : fdt->nr++;
1092 [ - + ]: 45 : if (pid_rst_prio(item->pid.virt, fdt->pid))
1093 : 0 : fdt->pid = item->pid.virt;
1094 : :
1095 : : return 0;
1096 : : }
|