Branch data Line data Source code
1 : : #include <sys/socket.h>
2 : : #include <linux/netlink.h>
3 : : #include <linux/rtnetlink.h>
4 : : #include <unistd.h>
5 : : #include <netinet/tcp.h>
6 : : #include <sys/stat.h>
7 : : #include <fcntl.h>
8 : : #include <sys/un.h>
9 : : #include <stdlib.h>
10 : : #include <dlfcn.h>
11 : :
12 : : #include "asm/types.h"
13 : : #include "libnetlink.h"
14 : : #include "cr_options.h"
15 : : #include "fdset.h"
16 : : #include "unix_diag.h"
17 : : #include "files.h"
18 : : #include "file-ids.h"
19 : : #include "image.h"
20 : : #include "log.h"
21 : : #include "util.h"
22 : : #include "util-pie.h"
23 : : #include "sockets.h"
24 : : #include "sk-queue.h"
25 : : #include "mount.h"
26 : : #include "cr-service.h"
27 : : #include "plugin.h"
28 : : #include "namespaces.h"
29 : : #include "pstree.h"
30 : :
31 : : #include "protobuf.h"
32 : : #include "protobuf/sk-unix.pb-c.h"
33 : :
34 : : struct unix_sk_desc {
35 : : struct socket_desc sd;
36 : : unsigned int type;
37 : : unsigned int state;
38 : : unsigned int peer_ino;
39 : : unsigned int rqlen;
40 : : unsigned int wqlen;
41 : : unsigned int namelen;
42 : : char *name;
43 : : unsigned int nr_icons;
44 : : unsigned int *icons;
45 : : unsigned char shutdown;
46 : :
47 : : mode_t mode;
48 : : uid_t uid;
49 : : gid_t gid;
50 : :
51 : : struct list_head list;
52 : :
53 : : int fd;
54 : : struct list_head peer_list;
55 : : struct list_head peer_node;
56 : :
57 : : UnixSkEntry *ue;
58 : : };
59 : :
60 : : static LIST_HEAD(unix_sockets);
61 : :
62 : : struct unix_sk_listen_icon {
63 : : unsigned int peer_ino;
64 : : struct unix_sk_desc *sk_desc;
65 : : struct unix_sk_listen_icon *next;
66 : : };
67 : :
68 : : #define SK_HASH_SIZE 32
69 : :
70 : : static struct unix_sk_listen_icon *unix_listen_icons[SK_HASH_SIZE];
71 : :
72 : : static struct unix_sk_listen_icon *lookup_unix_listen_icons(int peer_ino)
73 : : {
74 : : struct unix_sk_listen_icon *ic;
75 : :
76 [ + + ]: 8 : for (ic = unix_listen_icons[peer_ino % SK_HASH_SIZE];
77 : 0 : ic; ic = ic->next)
78 [ - + ]: 4 : if (ic->peer_ino == peer_ino)
79 : : return ic;
80 : : return NULL;
81 : : }
82 : :
83 : 133684 : static void show_one_unix(char *act, const struct unix_sk_desc *sk)
84 : : {
85 : 133684 : pr_debug("\t%s: ino %#x peer_ino %#x family %4d type %4d state %2d name %s\n",
86 : : act, sk->sd.ino, sk->peer_ino, sk->sd.family, sk->type, sk->state, sk->name);
87 : :
88 [ + + ]: 133684 : if (sk->nr_icons) {
89 : : int i;
90 : :
91 [ + + ]: 16 : for (i = 0; i < sk->nr_icons; i++)
92 : 8 : pr_debug("\t\ticon: %4d\n", sk->icons[i]);
93 : : }
94 : 133684 : }
95 : :
96 : 120 : static void show_one_unix_img(const char *act, const UnixSkEntry *e)
97 : : {
98 : 120 : pr_info("\t%s: id %#x ino %#x peer %#x type %d state %d name %d bytes\n",
99 : : act, e->id, e->ino, e->peer, e->type, e->state, (int)e->name.len);
100 : 120 : }
101 : :
102 : 236 : static int can_dump_unix_sk(const struct unix_sk_desc *sk)
103 : : {
104 : : /*
105 : : * The last case in this "if" is seqpacket socket,
106 : : * that is connected to cr_service. We will dump
107 : : * it properly below.
108 : : */
109 [ - + ]: 118 : if (sk->type != SOCK_STREAM &&
110 : 118 : sk->type != SOCK_DGRAM &&
111 : : sk->type != SOCK_SEQPACKET) {
112 : 0 : pr_err("Unsupported type (%d) on socket %x.\n"
113 : : "Only stream/dgram/seqpacket are supported.\n",
114 : : sk->type, sk->sd.ino);
115 : : return 0;
116 : : }
117 : :
118 [ + - ][ - + ]: 118 : switch (sk->state) {
119 : : case TCP_LISTEN:
120 : : case TCP_ESTABLISHED:
121 : : case TCP_CLOSE:
122 : : break;
123 : : default:
124 : 0 : pr_err("Unknown state %d for unix socket %x\n",
125 : : sk->state, sk->sd.ino);
126 : : return 0;
127 : : }
128 : :
129 : : return 1;
130 : : }
131 : :
132 : 236 : static int write_unix_entry(struct unix_sk_desc *sk)
133 : : {
134 : : int ret;
135 : :
136 : 118 : ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), sk->ue, PB_UNIX_SK);
137 : :
138 : 118 : show_one_unix_img("Dumped", sk->ue);
139 : :
140 : 118 : release_skopts(sk->ue->opts);
141 [ + - ]: 118 : xfree(sk->ue);
142 : :
143 : 118 : sk->ue = NULL;
144 : :
145 : 118 : return ret;
146 : : }
147 : :
148 : 118 : static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
149 : : {
150 : 118 : struct unix_sk_desc *sk, *peer;
151 : : UnixSkEntry *ue;
152 : : SkOptsEntry *skopts;
153 : : FilePermsEntry *perms;
154 : : FownEntry *fown;
155 : :
156 [ - + ]: 118 : ue = xmalloc(sizeof(UnixSkEntry) +
157 : : sizeof(SkOptsEntry) +
158 : : sizeof(FilePermsEntry) +
159 : : sizeof(FownEntry));
160 [ + - ]: 118 : if (ue == NULL)
161 : : return -1;
162 : :
163 : 118 : skopts = (void *) ue + sizeof(UnixSkEntry);
164 : 118 : perms = (void *) skopts + sizeof(SkOptsEntry);
165 : 118 : fown = (void *) perms + sizeof(FilePermsEntry);
166 : :
167 : 118 : unix_sk_entry__init(ue);
168 : 118 : sk_opts_entry__init(skopts);
169 : 118 : file_perms_entry__init(perms);
170 : :
171 : 118 : *fown = p->fown;
172 : :
173 : 118 : sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX, 0);
174 [ - + ]: 118 : if (IS_ERR_OR_NULL(sk)) {
175 : 0 : pr_err("Unix socket %#x not found\n", (int)p->stat.st_ino);
176 : 0 : goto err;
177 : : }
178 : :
179 [ + - ]: 118 : if (!can_dump_unix_sk(sk))
180 : : goto err;
181 : :
182 [ - + ]: 118 : BUG_ON(sk->sd.already_dumped);
183 : :
184 : 118 : ue->name.len = (size_t)sk->namelen;
185 : 118 : ue->name.data = (void *)sk->name;
186 : :
187 : 118 : ue->id = id;
188 : 118 : ue->ino = sk->sd.ino;
189 : 118 : ue->type = sk->type;
190 : 118 : ue->state = sk->state;
191 : 118 : ue->flags = p->flags;
192 : 118 : ue->backlog = sk->wqlen;
193 : 118 : ue->peer = sk->peer_ino;
194 : 118 : ue->fown = fown;
195 : 118 : ue->opts = skopts;
196 : 118 : ue->uflags = 0;
197 : :
198 : : /*
199 : : * Check if this socket is connected to criu service.
200 : : * Dump it like closed one and mark it for restore.
201 : : */
202 [ - + ]: 118 : if (unlikely(ue->peer == service_sk_ino)) {
203 : 0 : ue->state = TCP_CLOSE;
204 : 0 : ue->peer = 0;
205 : 0 : ue->uflags |= USK_SERVICE;
206 : : }
207 : :
208 [ + + ][ + + ]: 118 : if (sk->namelen && *sk->name) {
209 : 20 : ue->file_perms = perms;
210 : :
211 : 20 : perms->mode = sk->mode;
212 : 20 : perms->uid = sk->uid;
213 : 20 : perms->gid = sk->gid;
214 : : }
215 : :
216 [ + + ]: 118 : sk_encode_shutdown(ue, sk->shutdown);
217 : :
218 [ + + ]: 118 : if (ue->peer) {
219 : 86 : peer = (struct unix_sk_desc *)lookup_socket(ue->peer, PF_UNIX, 0);
220 [ - + ]: 86 : if (IS_ERR_OR_NULL(peer)) {
221 : 0 : pr_err("Unix socket %#x without peer %#x\n",
222 : : ue->ino, ue->peer);
223 : 0 : goto err;
224 : : }
225 : :
226 : : /*
227 : : * Peer should have us as peer or have a name by which
228 : : * we can access one.
229 : : */
230 [ + + ]: 86 : if (peer->peer_ino != ue->ino) {
231 [ - + ]: 10 : if (!peer->name) {
232 : 0 : pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
233 : : ue->ino, ue->peer, peer->peer_ino, peer->name);
234 : 0 : goto err;
235 : : }
236 : : }
237 : :
238 : : /*
239 : : * It can be external socket, so we defer dumping
240 : : * until all sockets the program owns are processed.
241 : : */
242 [ + + ]: 86 : if (!peer->sd.already_dumped) {
243 [ + + ]: 50 : if (list_empty(&peer->list)) {
244 : 46 : show_one_unix("Add a peer", peer);
245 : : list_add_tail(&peer->list, &unix_sockets);
246 : : }
247 : :
248 : 50 : list_add(&sk->peer_node, &peer->peer_list);
249 : 50 : sk->fd = dup(lfd);
250 [ - + ]: 50 : if (sk->fd < 0) {
251 : 0 : pr_perror("Unable to dup(%d)", lfd);
252 : 0 : goto err;
253 : : }
254 : : }
255 : :
256 [ + + ][ + + ]: 86 : if ((ue->type != SOCK_DGRAM) && (
257 [ + - ]: 4 : ((ue->shutdown == SK_SHUTDOWN__READ) &&
258 [ + + ]: 40 : (peer->shutdown != SK_SHUTDOWN__WRITE)) ||
259 [ + - ]: 4 : ((ue->shutdown == SK_SHUTDOWN__WRITE) &&
260 [ + + ]: 40 : (peer->shutdown != SK_SHUTDOWN__READ)) ||
261 [ - + ]: 8 : ((ue->shutdown == SK_SHUTDOWN__BOTH) &&
262 : 8 : (peer->shutdown != SK_SHUTDOWN__BOTH)) )) {
263 : : /*
264 : : * On restore we assume, that stream pairs must
265 : : * be shut down from one end only
266 : : */
267 : 0 : pr_err("Shutdown mismatch %u:%d -> %u:%d\n",
268 : : ue->ino, ue->shutdown, peer->sd.ino, peer->shutdown);
269 : 0 : goto err;
270 : : }
271 [ + + ]: 32 : } else if (ue->state == TCP_ESTABLISHED) {
272 : : const struct unix_sk_listen_icon *e;
273 : :
274 : 8 : e = lookup_unix_listen_icons(ue->ino);
275 [ + + ]: 8 : if (!e) {
276 : : /*
277 : : * ESTABLISHED socket without peer and without
278 : : * anyone waiting for it should be semi-closed
279 : : * connection.
280 : : */
281 : :
282 [ + - ]: 4 : if (ue->shutdown == SK_SHUTDOWN__BOTH) {
283 : 4 : pr_info("Dumping semi-closed connection\n");
284 : 4 : goto dump;
285 : : }
286 : :
287 : 0 : pr_err("Dangling connection %#x\n", ue->ino);
288 : 0 : goto err;
289 : : }
290 : :
291 : : /*
292 : : * If this is in-flight connection we need to figure
293 : : * out where to connect it on restore. Thus, tune up peer
294 : : * id by searching an existing listening socket.
295 : : *
296 : : * Note the socket name will be found at restore stage,
297 : : * not now, just to reduce size of dump files.
298 : : */
299 : :
300 : : /* e->sk_desc is _never_ NULL */
301 [ - + ]: 4 : if (e->sk_desc->state != TCP_LISTEN) {
302 : 0 : pr_err("In-flight connection on "
303 : : "non-listening socket %d\n", ue->ino);
304 : 0 : goto err;
305 : : }
306 : :
307 : 4 : ue->peer = e->sk_desc->sd.ino;
308 : :
309 : 4 : pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
310 : : ue->ino, ue->peer);
311 : : }
312 : : dump:
313 [ + - ]: 118 : if (dump_socket_opts(lfd, skopts))
314 : : goto err;
315 : :
316 : : /*
317 : : * If a stream listening socket has non-zero rqueue, this
318 : : * means there are in-flight connections waiting to get
319 : : * accept()-ed. We handle them separately with the "icons"
320 : : * (i stands for in-flight, cons -- for connections) things.
321 : : */
322 [ + + ][ + + ]: 118 : if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
323 : : sk->state == TCP_LISTEN))
324 [ + - ]: 24 : if (dump_sk_queue(lfd, id))
325 : : goto err;
326 : :
327 : 118 : pr_info("Dumping unix socket at %d\n", p->fd);
328 : 118 : show_one_unix("Dumping", sk);
329 : :
330 : 118 : sk->ue = ue;
331 : : /*
332 : : * Postpone writing the entry if a peer isn't found yet.
333 : : * It's required, because we may need to modify the entry.
334 : : * For example, if a socket is external and is dumped by
335 : : * a callback, the USK_CALLBACK flag must be set.
336 : : */
337 [ + + ][ + - ]: 118 : if (list_empty(&sk->peer_node) && write_unix_entry(sk))
338 : : return -1;
339 : :
340 : 118 : list_del_init(&sk->list);
341 : 118 : sk->sd.already_dumped = 1;
342 : :
343 [ + + ]: 166 : while (!list_empty(&sk->peer_list)) {
344 : : struct unix_sk_desc *psk;
345 : : psk = list_first_entry(&sk->peer_list, struct unix_sk_desc, peer_node);
346 : 48 : close_safe(&psk->fd);
347 : 48 : list_del_init(&psk->peer_node);
348 : :
349 [ + - ]: 48 : if (write_unix_entry(psk))
350 : : return -1;
351 : : }
352 : :
353 : : return 0;
354 : :
355 : : err:
356 : 0 : release_skopts(skopts);
357 [ # # ]: 0 : xfree(ue);
358 : : return -1;
359 : : }
360 : :
361 : : const struct fdtype_ops unix_dump_ops = {
362 : : .type = FD_TYPES__UNIXSK,
363 : : .dump = dump_one_unix_fd,
364 : : };
365 : :
366 : 133518 : static int unix_collect_one(const struct unix_diag_msg *m,
367 : : struct rtattr **tb)
368 : : {
369 : : struct unix_sk_desc *d;
370 : : char *name = NULL;
371 : : struct ns_id *ns;
372 : : int ret = 0;
373 : :
374 : 133518 : ns = lookup_ns_by_id(root_item->ids->mnt_ns_id, &mnt_ns_desc);
375 [ + - ]: 133518 : if (ns == NULL)
376 : : return -1;
377 : :
378 [ + - ]: 133518 : if (mntns_collect_root(ns->pid) < 0)
379 : : return -1;
380 : :
381 [ - + ]: 133518 : d = xzalloc(sizeof(*d));
382 [ + - ]: 133518 : if (!d)
383 : : return -1;
384 : :
385 : 133518 : d->type = m->udiag_type;
386 : 133518 : d->state = m->udiag_state;
387 : 133518 : INIT_LIST_HEAD(&d->list);
388 : :
389 : 133518 : INIT_LIST_HEAD(&d->peer_list);
390 : 133518 : INIT_LIST_HEAD(&d->peer_node);
391 : 133518 : d->fd = -1;
392 : :
393 [ + - ]: 133518 : if (tb[UNIX_DIAG_SHUTDOWN])
394 : 133518 : d->shutdown = *(u8 *)RTA_DATA(tb[UNIX_DIAG_SHUTDOWN]);
395 : : else
396 [ # # ]: 0 : pr_err_once("No socket shutdown info\n");
397 : :
398 [ + + ]: 133518 : if (tb[UNIX_DIAG_PEER])
399 : 125704 : d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]);
400 : :
401 [ + + ]: 133518 : if (tb[UNIX_DIAG_NAME]) {
402 : 53993 : int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
403 : :
404 [ - + ]: 53993 : name = xmalloc(len + 1);
405 [ + - ]: 53993 : if (!name)
406 : : goto err;
407 : :
408 : 53993 : memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
409 : 53993 : name[len] = '\0';
410 : :
411 [ + + ]: 53993 : if (name[0] != '\0') {
412 : : struct unix_diag_vfs *uv;
413 : : struct stat st;
414 : : char rpath[PATH_MAX];
415 : : bool drop_path = false;
416 : : int mntns_root;
417 : :
418 [ - + ]: 18825 : if (name[0] != '/') {
419 : 0 : pr_warn("Relative bind path '%s' "
420 : : "unsupported\n", name);
421 : 0 : goto skip;
422 : : }
423 : :
424 [ - + ]: 18825 : if (!tb[UNIX_DIAG_VFS]) {
425 : 0 : pr_err("Bound socket w/o inode %#x\n",
426 : : m->udiag_ino);
427 : 0 : goto skip;
428 : : }
429 : :
430 : 18825 : mntns_root = get_service_fd(ROOT_FD_OFF);
431 : :
432 : 18825 : uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
433 : : snprintf(rpath, sizeof(rpath), ".%s", name);
434 [ - + ]: 18825 : if (fstatat(mntns_root, rpath, &st, 0)) {
435 [ # # ]: 0 : if (errno != ENOENT) {
436 : 0 : pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n",
437 : : m->udiag_ino, rpath, errno);
438 : 0 : goto skip;
439 : : }
440 : :
441 : 0 : pr_info("unix: Dropping path %s for unlinked sk %#x\n",
442 : : name, m->udiag_ino);
443 : : drop_path = true;
444 [ + - - + ]: 37650 : } else if ((st.st_ino != uv->udiag_vfs_ino) ||
445 : 18825 : !phys_stat_dev_match(ns->mnt.mntinfo_tree, st.st_dev,
446 : 18825 : uv->udiag_vfs_dev, name)) {
447 : 0 : pr_info("unix: Dropping path %s for "
448 : : "unlinked bound "
449 : : "sk %#x.%#x real %#x.%#x\n",
450 : : name,
451 : : (int)st.st_dev,
452 : : (int)st.st_ino,
453 : : (int)uv->udiag_vfs_dev,
454 : : (int)uv->udiag_vfs_ino);
455 : : drop_path = true;
456 : : }
457 : :
458 [ - + ]: 18825 : if (drop_path) {
459 : : /*
460 : : * When a socket is bound to unlinked file, we
461 : : * just drop his name, since no one will access
462 : : * it via one.
463 : : */
464 [ # # ]: 0 : xfree(name);
465 : : len = 0;
466 : : name = NULL;
467 : : }
468 : :
469 : 18825 : d->mode = st.st_mode;
470 : 18825 : d->uid = st.st_uid;
471 : 18825 : d->gid = st.st_gid;
472 : : }
473 : :
474 : 53993 : d->namelen = len;
475 : 53993 : d->name = name;
476 : : }
477 : :
478 [ + + ]: 133518 : if (tb[UNIX_DIAG_ICONS]) {
479 : 6848 : int len = RTA_PAYLOAD(tb[UNIX_DIAG_ICONS]);
480 : : int i;
481 : :
482 [ - + ]: 6848 : d->icons = xmalloc(len);
483 [ + - ]: 6848 : if (!d->icons)
484 : : goto err;
485 : :
486 : 6848 : memcpy(d->icons, RTA_DATA(tb[UNIX_DIAG_ICONS]), len);
487 : 6848 : d->nr_icons = len / sizeof(u32);
488 : :
489 : : /*
490 : : * Remember these sockets, we will need them
491 : : * to fix up in-flight sockets peers.
492 : : */
493 [ + + ]: 6852 : for (i = 0; i < d->nr_icons; i++) {
494 : : struct unix_sk_listen_icon *e, **chain;
495 : : int n;
496 : :
497 [ - + ]: 4 : e = xzalloc(sizeof(*e));
498 [ + - ]: 4 : if (!e)
499 : : goto err;
500 : :
501 : 4 : n = d->icons[i];
502 : 4 : chain = &unix_listen_icons[n % SK_HASH_SIZE];
503 : 4 : e->next = *chain;
504 : 4 : *chain = e;
505 : :
506 : 4 : pr_debug("\t\tCollected icon %d\n", d->icons[i]);
507 : :
508 : 4 : e->peer_ino = n;
509 : 4 : e->sk_desc = d;
510 : : }
511 : :
512 : :
513 : : }
514 : :
515 [ + - ]: 133518 : if (tb[UNIX_DIAG_RQLEN]) {
516 : : struct unix_diag_rqlen *rq;
517 : :
518 : : rq = (struct unix_diag_rqlen *)RTA_DATA(tb[UNIX_DIAG_RQLEN]);
519 : 133518 : d->rqlen = rq->udiag_rqueue;
520 : 133518 : d->wqlen = rq->udiag_wqueue;
521 : : }
522 : :
523 : 133518 : sk_collect_one(m->udiag_ino, AF_UNIX, &d->sd);
524 : 133518 : show_one_unix("Collected", d);
525 : :
526 : 133518 : return 0;
527 : : err:
528 : : ret = -1;
529 : : skip:
530 [ # # ]: 0 : xfree(d->icons);
531 [ # # ]: 0 : xfree(name);
532 [ # # ]: 0 : xfree(d);
533 : 0 : return ret;
534 : : }
535 : :
536 : 133518 : int unix_receive_one(struct nlmsghdr *h, void *arg)
537 : : {
538 : 133518 : struct unix_diag_msg *m = NLMSG_DATA(h);
539 : : struct rtattr *tb[UNIX_DIAG_MAX+1];
540 : :
541 : 133518 : parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr *)(m + 1),
542 : 133518 : h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
543 : :
544 : 133518 : return unix_collect_one(m, tb);
545 : : }
546 : :
547 : 2 : static int dump_external_sockets(struct unix_sk_desc *peer)
548 : : {
549 : : struct unix_sk_desc *sk;
550 : : int ret;
551 : :
552 [ + + ]: 4 : while (!list_empty(&peer->peer_list)) {
553 : : sk = list_first_entry(&peer->peer_list, struct unix_sk_desc, peer_node);
554 : :
555 : 2 : ret = cr_plugin_dump_unix_sk(sk->fd, sk->sd.ino);
556 [ + - ]: 2 : if (ret == -ENOTSUP) {
557 [ - + ]: 2 : if (!opts.ext_unix_sk) {
558 : 0 : show_one_unix("Runaway socket", peer);
559 : 0 : pr_err("External socket is used. "
560 : : "Consider using --" USK_EXT_PARAM " option.\n");
561 : 0 : return -1;
562 : : }
563 : :
564 [ - + ]: 2 : if (peer->type != SOCK_DGRAM) {
565 : 0 : show_one_unix("Ext stream not supported", peer);
566 : 0 : pr_err("Can't dump half of stream unix connection.\n");
567 : 0 : return -1;
568 : : }
569 [ # # ]: 0 : } else if (ret < 0)
570 : : return -1;
571 : : else
572 : 0 : sk->ue->uflags |= USK_CALLBACK;
573 : :
574 [ + - ]: 2 : if (write_unix_entry(sk))
575 : : return -1;
576 : 2 : close_safe(&sk->fd);
577 : 2 : list_del_init(&sk->peer_node);
578 : : }
579 : :
580 : : return 0;
581 : : }
582 : :
583 : 448 : int fix_external_unix_sockets(void)
584 : : {
585 : : struct unix_sk_desc *sk;
586 : :
587 : 448 : pr_debug("Dumping external sockets\n");
588 : :
589 [ + + ]: 450 : list_for_each_entry(sk, &unix_sockets, list) {
590 : 2 : UnixSkEntry e = UNIX_SK_ENTRY__INIT;
591 : 2 : FownEntry fown = FOWN_ENTRY__INIT;
592 : 2 : SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
593 : :
594 : 2 : show_one_unix("Dumping extern", sk);
595 : :
596 [ - + ]: 2 : BUG_ON(sk->sd.already_dumped);
597 : :
598 : 2 : fd_id_generate_special(NULL, &e.id);
599 : 2 : e.ino = sk->sd.ino;
600 : 2 : e.type = SOCK_DGRAM;
601 : 2 : e.state = TCP_LISTEN;
602 : 2 : e.name.data = (void *)sk->name;
603 : 2 : e.name.len = (size_t)sk->namelen;
604 : 2 : e.uflags = USK_EXTERN;
605 : 2 : e.peer = 0;
606 : 2 : e.fown = &fown;
607 : 2 : e.opts = &skopts;
608 : :
609 [ + - ]: 2 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &e, PB_UNIX_SK))
610 : : goto err;
611 : :
612 : 2 : show_one_unix_img("Dumped extern", &e);
613 : :
614 [ + - ]: 2 : if (dump_external_sockets(sk))
615 : : goto err;
616 : : }
617 : :
618 : : return 0;
619 : : err:
620 : 0 : return -1;
621 : : }
622 : :
623 : : struct unix_sk_info {
624 : : UnixSkEntry *ue;
625 : : struct list_head list;
626 : : char *name;
627 : : unsigned flags;
628 : : struct unix_sk_info *peer;
629 : : struct file_desc d;
630 : : futex_t bound;
631 : : };
632 : :
633 : : #define USK_PAIR_MASTER 0x1
634 : : #define USK_PAIR_SLAVE 0x2
635 : :
636 : : static struct unix_sk_info *find_unix_sk_by_ino(int ino)
637 : : {
638 : : struct unix_sk_info *ui;
639 : :
640 [ + - ]: 112 : list_for_each_entry(ui, &unix_sockets, list) {
641 [ + + ]: 112 : if (ui->ue->ino == ino)
642 : : return ui;
643 : : }
644 : :
645 : : return NULL;
646 : : }
647 : :
648 : 72 : static int shutdown_unix_sk(int sk, struct unix_sk_info *ui)
649 : : {
650 : : int how;
651 : 36 : UnixSkEntry *ue = ui->ue;
652 : :
653 [ + + ][ + - ]: 36 : if (!ue->has_shutdown || ue->shutdown == SK_SHUTDOWN__NONE)
654 : : return 0;
655 : :
656 : 10 : how = sk_decode_shutdown(ue->shutdown);
657 [ - + ]: 10 : if (shutdown(sk, how)) {
658 : 0 : pr_perror("Can't shutdown unix socket");
659 : : return -1;
660 : : }
661 : :
662 : 10 : pr_debug("Socket %#x is shut down %d\n", ue->ino, how);
663 : : return 0;
664 : : }
665 : :
666 : 60 : static int post_open_unix_sk(struct file_desc *d, int fd)
667 : : {
668 : 10 : struct unix_sk_info *ui;
669 : : struct unix_sk_info *peer;
670 : : struct sockaddr_un addr;
671 : :
672 : : ui = container_of(d, struct unix_sk_info, d);
673 [ + + ]: 60 : if (ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))
674 : : return 0;
675 : :
676 : 24 : peer = ui->peer;
677 : :
678 [ + + ]: 24 : if (peer == NULL)
679 : : return 0;
680 : :
681 [ + - ]: 10 : if (ui->ue->uflags & USK_CALLBACK)
682 : : return 0;
683 : :
684 : 10 : pr_info("\tConnect %#x to %#x\n", ui->ue->ino, peer->ue->ino);
685 : :
686 : : /* Skip external sockets */
687 [ + + ]: 10 : if (!list_empty(&peer->d.fd_info_head))
688 : 8 : futex_wait_while(&peer->bound, 0);
689 : :
690 : : memset(&addr, 0, sizeof(addr));
691 : 10 : addr.sun_family = AF_UNIX;
692 : 10 : memcpy(&addr.sun_path, peer->name, peer->ue->name.len);
693 : :
694 [ - + ]: 10 : if (connect(fd, (struct sockaddr *)&addr,
695 : : sizeof(addr.sun_family) +
696 : 10 : peer->ue->name.len) < 0) {
697 : 0 : pr_perror("Can't connect %#x socket", ui->ue->ino);
698 : 0 : return -1;
699 : : }
700 : :
701 [ + - ]: 10 : if (restore_sk_queue(fd, peer->ue->id))
702 : : return -1;
703 : :
704 [ + - ]: 10 : if (rst_file_params(fd, ui->ue->fown, ui->ue->flags))
705 : : return -1;
706 : :
707 [ + - ]: 10 : if (restore_socket_opts(fd, ui->ue->opts))
708 : : return -1;
709 : :
710 [ + - ]: 10 : if (shutdown_unix_sk(fd, ui))
711 : : return -1;
712 : :
713 : 10 : return 0;
714 : : }
715 : :
716 : 60 : static int bind_unix_sk(int sk, struct unix_sk_info *ui)
717 : : {
718 : : struct sockaddr_un addr;
719 : :
720 [ + + ]: 60 : if ((ui->ue->type == SOCK_STREAM) && (ui->ue->state == TCP_ESTABLISHED))
721 : : /*
722 : : * FIXME this can be done, but for doing this properly we
723 : : * need to bind socket to its name, then rename one to
724 : : * some temporary unique one and after all the sockets are
725 : : * restored we should walk those temp names and rename
726 : : * some of them back to real ones.
727 : : */
728 : : goto done;
729 : :
730 : : memset(&addr, 0, sizeof(addr));
731 : 36 : addr.sun_family = AF_UNIX;
732 : 36 : memcpy(&addr.sun_path, ui->name, ui->ue->name.len);
733 : :
734 [ - + ]: 36 : if (bind(sk, (struct sockaddr *)&addr,
735 : 36 : sizeof(addr.sun_family) + ui->ue->name.len)) {
736 : 0 : pr_perror("Can't bind socket");
737 : 0 : return -1;
738 : : }
739 : :
740 [ + + ][ + + ]: 36 : if (ui->ue->name.len && *ui->name && ui->ue->file_perms) {
[ + - ]
741 : : FilePermsEntry *perms = ui->ue->file_perms;
742 : : char fname[PATH_MAX];
743 : :
744 [ - + ]: 8 : if (ui->ue->name.len >= sizeof(fname)) {
745 : 0 : pr_err("The file name is too long\n");
746 : 0 : return -1;
747 : : }
748 : :
749 : : memcpy(fname, ui->name, ui->ue->name.len);
750 : 8 : fname[ui->ue->name.len] = '\0';
751 : :
752 [ - + ]: 8 : if (chown(fname, perms->uid, perms->gid) == -1) {
753 : 0 : pr_perror("Unable to change file owner and group");
754 : 0 : return -1;
755 : : }
756 : :
757 [ - + ]: 8 : if (chmod(fname, perms->mode) == -1) {
758 : 0 : pr_perror("Unable to change file mode bits");
759 : 8 : return -1;
760 : : }
761 : : }
762 : :
763 : 36 : futex_set_and_wake(&ui->bound, 1);
764 : : done:
765 : : return 0;
766 : : }
767 : :
768 : 60 : static int unixsk_should_open_transport(FdinfoEntry *fe,
769 : : struct file_desc *d)
770 : : {
771 : : struct unix_sk_info *ui;
772 : :
773 : : ui = container_of(d, struct unix_sk_info, d);
774 : 60 : return ui->flags & USK_PAIR_SLAVE;
775 : : }
776 : :
777 : 18 : static int open_unixsk_pair_master(struct unix_sk_info *ui)
778 : : {
779 : : int sk[2], tsk;
780 : 18 : struct unix_sk_info *peer = ui->peer;
781 : : struct fdinfo_list_entry *fle;
782 : :
783 : 18 : pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
784 : : ui->ue->id, ui->ue->ino, ui->ue->peer);
785 : :
786 [ - + ]: 18 : if (socketpair(PF_UNIX, ui->ue->type, 0, sk) < 0) {
787 : 0 : pr_perror("Can't make socketpair");
788 : 0 : return -1;
789 : : }
790 : :
791 [ + - ]: 18 : if (restore_sk_queue(sk[0], peer->ue->id))
792 : : return -1;
793 [ + - ]: 18 : if (restore_sk_queue(sk[1], ui->ue->id))
794 : : return -1;
795 : :
796 [ + - ]: 18 : if (bind_unix_sk(sk[0], ui))
797 : : return -1;
798 : :
799 [ + - ]: 18 : if (rst_file_params(sk[0], ui->ue->fown, ui->ue->flags))
800 : : return -1;
801 : :
802 [ + - ]: 18 : if (restore_socket_opts(sk[0], ui->ue->opts))
803 : : return -1;
804 : :
805 [ + - ]: 18 : if (shutdown_unix_sk(sk[0], ui))
806 : : return -1;
807 : :
808 : 18 : tsk = socket(PF_UNIX, SOCK_DGRAM, 0);
809 [ - + ]: 18 : if (tsk < 0) {
810 : 0 : pr_perror("Can't make transport socket");
811 : 0 : return -1;
812 : : }
813 : :
814 : 18 : fle = file_master(&peer->d);
815 [ - + ]: 18 : if (send_fd_to_peer(sk[1], fle, tsk)) {
816 : 0 : pr_err("Can't send pair slave\n");
817 : 0 : return -1;
818 : : }
819 : :
820 : 18 : close(tsk);
821 : 18 : close(sk[1]);
822 : :
823 : 18 : return sk[0];
824 : : }
825 : :
826 : 18 : static int open_unixsk_pair_slave(struct unix_sk_info *ui)
827 : : {
828 : : struct fdinfo_list_entry *fle;
829 : : int sk;
830 : :
831 : 18 : fle = file_master(&ui->d);
832 : :
833 : 18 : pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
834 : : ui->ue->id, ui->ue->ino, ui->ue->peer, fle->fe->fd);
835 : :
836 : 18 : sk = recv_fd(fle->fe->fd);
837 [ - + ]: 18 : if (sk < 0) {
838 : 0 : pr_err("Can't recv pair slave");
839 : 0 : return -1;
840 : : }
841 : 18 : close(fle->fe->fd);
842 : :
843 [ + - ]: 18 : if (bind_unix_sk(sk, ui))
844 : : return -1;
845 : :
846 [ + - ]: 18 : if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
847 : : return -1;
848 : :
849 [ + - ]: 18 : if (restore_socket_opts(sk, ui->ue->opts))
850 : : return -1;
851 : :
852 [ + + ]: 18 : if (ui->ue->type == SOCK_DGRAM)
853 : : /*
854 : : * Stream socket's "slave" end will be shut down
855 : : * together with master
856 : : */
857 [ + - ]: 8 : if (shutdown_unix_sk(sk, ui))
858 : : return -1;
859 : :
860 : 18 : return sk;
861 : : }
862 : :
863 : 24 : static int open_unixsk_standalone(struct unix_sk_info *ui)
864 : : {
865 : : int sk;
866 : :
867 : 24 : pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
868 : : ui->ue->id, ui->ue->ino, ui->ue->peer);
869 : :
870 : : /*
871 : : * Check if this socket was connected to criu service.
872 : : * If so, put response, that dumping and restoring
873 : : * was successful.
874 : : */
875 [ - + ]: 24 : if (ui->ue->uflags & USK_SERVICE) {
876 : : int sks[2];
877 : :
878 [ # # ]: 0 : if (socketpair(PF_UNIX, ui->ue->type, 0, sks)) {
879 : 0 : pr_perror("Can't create socketpair");
880 : 0 : return -1;
881 : : }
882 : :
883 [ # # ]: 0 : if (send_criu_dump_resp(sks[1], true, true) == -1)
884 : : return -1;
885 : :
886 : 0 : close(sks[1]);
887 : 0 : sk = sks[0];
888 [ + + ][ + + ]: 26 : } else if ((ui->ue->state == TCP_ESTABLISHED) && !ui->ue->peer) {
889 : : int ret, sks[2];
890 : :
891 [ - + ]: 2 : if (ui->ue->type != SOCK_STREAM) {
892 : 0 : pr_err("Non-stream socket %x in established state\n",
893 : : ui->ue->ino);
894 : 0 : return -1;
895 : : }
896 : :
897 [ - + ]: 2 : if (ui->ue->shutdown != SK_SHUTDOWN__BOTH) {
898 : 0 : pr_err("Wrong shutdown/peer state for %x\n",
899 : : ui->ue->ino);
900 : 0 : return -1;
901 : : }
902 : :
903 : 2 : ret = socketpair(PF_UNIX, ui->ue->type, 0, sks);
904 [ - + ]: 2 : if (ret < 0) {
905 : 0 : pr_perror("Can't create socketpair");
906 : 0 : return -1;
907 : : }
908 : :
909 : : /*
910 : : * Restore queue at the one end,
911 : : * before closing the second one.
912 : : */
913 [ - + ]: 2 : if (restore_sk_queue(sks[1], ui->ue->id)) {
914 : 0 : pr_perror("Can't restore socket queue");
915 : 0 : return -1;
916 : : }
917 : :
918 : 2 : close(sks[1]);
919 : 2 : sk = sks[0];
920 : : } else {
921 [ - + ]: 22 : if (ui->ue->uflags & USK_CALLBACK) {
922 : 0 : sk = cr_plugin_restore_unix_sk(ui->ue->ino);
923 [ # # ]: 0 : if (sk >= 0)
924 : : goto out;
925 : : }
926 : :
927 : : /*
928 : : * Connect to external sockets requires
929 : : * special option to be passed.
930 : : */
931 [ + + ][ + + ]: 22 : if (ui->peer && (ui->peer->ue->uflags & USK_EXTERN) &&
[ - + ]
932 : 2 : !(opts.ext_unix_sk)) {
933 : 0 : pr_err("External socket found in image. "
934 : : "Consider using the --" USK_EXT_PARAM
935 : : "option to allow restoring it.\n");
936 : 0 : return -1;
937 : : }
938 : :
939 : :
940 : 22 : sk = socket(PF_UNIX, ui->ue->type, 0);
941 [ - + ]: 22 : if (sk < 0) {
942 : 0 : pr_perror("Can't make unix socket");
943 : 0 : return -1;
944 : : }
945 : : }
946 : :
947 [ + - ]: 24 : if (bind_unix_sk(sk, ui))
948 : : return -1;
949 : :
950 [ + + ]: 24 : if (ui->ue->state == TCP_LISTEN) {
951 : 2 : pr_info("\tPutting %#x into listen state\n", ui->ue->ino);
952 [ - + ]: 2 : if (listen(sk, ui->ue->backlog) < 0) {
953 : 0 : pr_perror("Can't make usk listen");
954 : 0 : return -1;
955 : : }
956 : : }
957 : : out:
958 [ + - ]: 24 : if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
959 : : return -1;
960 : :
961 [ + - ]: 24 : if (restore_socket_opts(sk, ui->ue->opts))
962 : : return -1;
963 : :
964 : 24 : return sk;
965 : : }
966 : :
967 : 60 : static int open_unix_sk(struct file_desc *d)
968 : : {
969 : : struct unix_sk_info *ui;
970 : :
971 : 60 : ui = container_of(d, struct unix_sk_info, d);
972 [ + + ]: 60 : if (ui->flags & USK_PAIR_MASTER)
973 : 18 : return open_unixsk_pair_master(ui);
974 [ + + ]: 42 : else if (ui->flags & USK_PAIR_SLAVE)
975 : 18 : return open_unixsk_pair_slave(ui);
976 : : else
977 : 24 : return open_unixsk_standalone(ui);
978 : : }
979 : :
980 : : static struct file_desc_ops unix_desc_ops = {
981 : : .type = FD_TYPES__UNIXSK,
982 : : .open = open_unix_sk,
983 : : .post_open = post_open_unix_sk,
984 : : .want_transport = unixsk_should_open_transport,
985 : : };
986 : :
987 : 62 : static int collect_one_unixsk(void *o, ProtobufCMessage *base)
988 : : {
989 : : struct unix_sk_info *ui = o;
990 : :
991 : 62 : ui->ue = pb_msg(base, UnixSkEntry);
992 : :
993 [ + + ]: 62 : if (ui->ue->name.len) {
994 [ - + ]: 14 : if (ui->ue->name.len >= UNIX_PATH_MAX) {
995 : 0 : pr_err("Bad unix name len %d\n", (int)ui->ue->name.len);
996 : 0 : return -1;
997 : : }
998 : :
999 : 14 : ui->name = (void *)ui->ue->name.data;
1000 : :
1001 : : /*
1002 : : * Make FS clean from sockets we're about to
1003 : : * restore. See for how we bind them for details
1004 : : */
1005 [ + + ][ + + ]: 14 : if (ui->name[0] != '\0' &&
1006 : 12 : !(ui->ue->uflags & USK_EXTERN))
1007 : 10 : unlink(ui->name);
1008 : : } else
1009 : 48 : ui->name = NULL;
1010 : :
1011 : : futex_init(&ui->bound);
1012 : 62 : ui->peer = NULL;
1013 : 62 : ui->flags = 0;
1014 [ + + ][ + + ]: 62 : pr_info(" `- Got %#x peer %#x (name %s)\n",
1015 : : ui->ue->ino, ui->ue->peer,
1016 : : ui->name ? (ui->name[0] ? ui->name : &ui->name[1]) : "-");
1017 : 62 : list_add_tail(&ui->list, &unix_sockets);
1018 : 62 : return file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops);
1019 : : }
1020 : :
1021 : : struct collect_image_info unix_sk_cinfo = {
1022 : : .fd_type = CR_FD_UNIXSK,
1023 : : .pb_type = PB_UNIX_SK,
1024 : : .priv_size = sizeof(struct unix_sk_info),
1025 : : .collect = collect_one_unixsk,
1026 : : .flags = COLLECT_SHARED,
1027 : : };
1028 : :
1029 : 354 : int collect_unix_sockets(void)
1030 : : {
1031 : 354 : return read_sk_queues();
1032 : : }
1033 : :
1034 : 354 : int resolve_unix_peers(void)
1035 : : {
1036 : : struct unix_sk_info *ui, *peer;
1037 : 18 : struct fdinfo_list_entry *fle, *fle_peer;
1038 : :
1039 [ + + ]: 416 : list_for_each_entry(ui, &unix_sockets, list) {
1040 [ + + ]: 62 : if (ui->peer)
1041 : 18 : continue;
1042 [ + + ]: 44 : if (!ui->ue->peer)
1043 : 16 : continue;
1044 : :
1045 : : peer = find_unix_sk_by_ino(ui->ue->peer);
1046 : :
1047 [ - + ]: 28 : if (!peer) {
1048 : 0 : pr_err("FATAL: Peer %#x unresolved for %#x\n",
1049 : : ui->ue->peer, ui->ue->ino);
1050 : 0 : return -1;
1051 : : }
1052 : :
1053 : 28 : ui->peer = peer;
1054 [ + + ]: 28 : if (ui == peer)
1055 : : /* socket connected to self %) */
1056 : 2 : continue;
1057 [ + + ]: 26 : if (peer->ue->peer != ui->ue->ino)
1058 : 8 : continue;
1059 : :
1060 : : /* socketpair or interconnected sockets */
1061 : 18 : peer->peer = ui;
1062 : :
1063 : : /*
1064 : : * Select who will restore the pair. Check is identical to
1065 : : * the one in pipes.c and makes sure tasks wait for each other
1066 : : * in pids sorting order (ascending).
1067 : : */
1068 : :
1069 : 18 : fle = file_master(&ui->d);
1070 : 18 : fle_peer = file_master(&peer->d);
1071 : :
1072 [ - + ]: 18 : if (fdinfo_rst_prio(fle, fle_peer)) {
1073 : 0 : ui->flags |= USK_PAIR_MASTER;
1074 : 0 : peer->flags |= USK_PAIR_SLAVE;
1075 : : } else {
1076 : 18 : peer->flags |= USK_PAIR_MASTER;
1077 : 18 : ui->flags |= USK_PAIR_SLAVE;
1078 : : }
1079 : : }
1080 : :
1081 : 354 : pr_info("Unix sockets:\n");
1082 [ + + ]: 416 : list_for_each_entry(ui, &unix_sockets, list) {
1083 : : struct fdinfo_list_entry *fle;
1084 : :
1085 [ + + ]: 62 : pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue->ino, ui->ue->peer,
1086 : : ui->peer ? ui->peer->ue->ino : 0, ui->flags);
1087 [ + + ]: 122 : list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
1088 : 60 : pr_info("\t\tfd %d in pid %d\n",
1089 : : fle->fe->fd, fle->pid);
1090 : :
1091 : : }
1092 : :
1093 : : return 0;
1094 : : }
1095 : :
|