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 : :
11 : : #include "types.h"
12 : : #include "libnetlink.h"
13 : : #include "crtools.h"
14 : : #include "unix_diag.h"
15 : : #include "files.h"
16 : : #include "file-ids.h"
17 : : #include "image.h"
18 : : #include "log.h"
19 : : #include "util.h"
20 : : #include "util-net.h"
21 : : #include "sockets.h"
22 : : #include "sk-queue.h"
23 : : #include "mount.h"
24 : :
25 : : #include "protobuf.h"
26 : : #include "protobuf/sk-unix.pb-c.h"
27 : :
28 : : struct unix_sk_desc {
29 : : struct socket_desc sd;
30 : : unsigned int type;
31 : : unsigned int state;
32 : : unsigned int peer_ino;
33 : : unsigned int rqlen;
34 : : unsigned int wqlen;
35 : : unsigned int namelen;
36 : : char *name;
37 : : unsigned int nr_icons;
38 : : unsigned int *icons;
39 : : unsigned char shutdown;
40 : : struct list_head list;
41 : : };
42 : :
43 : : static LIST_HEAD(unix_sockets);
44 : :
45 : : struct unix_sk_listen_icon {
46 : : unsigned int peer_ino;
47 : : struct unix_sk_desc *sk_desc;
48 : : struct unix_sk_listen_icon *next;
49 : : };
50 : :
51 : : #define SK_HASH_SIZE 32
52 : :
53 : : static struct unix_sk_listen_icon *unix_listen_icons[SK_HASH_SIZE];
54 : :
55 : : static struct unix_sk_listen_icon *lookup_unix_listen_icons(int peer_ino)
56 : : {
57 : : struct unix_sk_listen_icon *ic;
58 : :
59 [ + - ]: 2 : for (ic = unix_listen_icons[peer_ino % SK_HASH_SIZE];
60 : 0 : ic; ic = ic->next)
61 [ - + ]: 2 : if (ic->peer_ino == peer_ino)
62 : : return ic;
63 : : return NULL;
64 : : }
65 : :
66 : 5009 : static void show_one_unix(char *act, const struct unix_sk_desc *sk)
67 : : {
68 : 5009 : pr_debug("\t%s: ino %#x peer_ino %#x family %4d type %4d state %2d name %s\n",
69 : : act, sk->sd.ino, sk->peer_ino, sk->sd.family, sk->type, sk->state, sk->name);
70 : :
71 [ + + ]: 5009 : if (sk->nr_icons) {
72 : : int i;
73 : :
74 [ + + ]: 8 : for (i = 0; i < sk->nr_icons; i++)
75 : 4 : pr_debug("\t\ticon: %4d\n", sk->icons[i]);
76 : : }
77 : 5009 : }
78 : :
79 : 58 : static void show_one_unix_img(const char *act, const UnixSkEntry *e)
80 : : {
81 : 58 : pr_info("\t%s: id %#x ino %#x peer %#x type %d state %d name %d bytes\n",
82 : : act, e->id, e->ino, e->peer, e->type, e->state, (int)e->name.len);
83 : 58 : }
84 : :
85 : 57 : static int can_dump_unix_sk(const struct unix_sk_desc *sk)
86 : : {
87 [ - + ]: 57 : if (sk->type != SOCK_STREAM &&
88 : : sk->type != SOCK_DGRAM) {
89 : 0 : pr_err("Only stream/dgram sockets for now\n");
90 : : return 0;
91 : : }
92 : :
93 [ - + ]: 57 : switch (sk->state) {
94 : : case TCP_LISTEN:
95 : : case TCP_ESTABLISHED:
96 : : case TCP_CLOSE:
97 : : break;
98 : : default:
99 : 57 : pr_err("Unknown state %d\n", sk->state);
100 : : return 0;
101 : : }
102 : :
103 : : return 1;
104 : : }
105 : :
106 : 57 : static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
107 : : {
108 : : struct unix_sk_desc *sk;
109 : 57 : UnixSkEntry ue = UNIX_SK_ENTRY__INIT;
110 : 57 : SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
111 : :
112 : 57 : sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX);
113 [ + - ]: 57 : if (!sk)
114 : : goto err;
115 : :
116 [ + - ]: 57 : if (!can_dump_unix_sk(sk))
117 : : goto err;
118 : :
119 [ - + ]: 57 : BUG_ON(sk->sd.already_dumped);
120 : :
121 : 57 : ue.name.len = (size_t)sk->namelen;
122 : 57 : ue.name.data = (void *)sk->name;
123 : :
124 : 57 : ue.id = id;
125 : 57 : ue.ino = sk->sd.ino;
126 : 57 : ue.type = sk->type;
127 : 57 : ue.state = sk->state;
128 : 57 : ue.flags = p->flags;
129 : 57 : ue.backlog = sk->wqlen;
130 : 57 : ue.peer = sk->peer_ino;
131 : 57 : ue.fown = (FownEntry *)&p->fown;
132 : 57 : ue.opts = &skopts;
133 : 57 : ue.uflags = 0;
134 : :
135 [ + + ]: 57 : sk_encode_shutdown(&ue, sk->shutdown);
136 : :
137 [ + + ]: 57 : if (ue.peer) {
138 : : struct unix_sk_desc *peer;
139 : :
140 : 43 : peer = (struct unix_sk_desc *)lookup_socket(ue.peer, PF_UNIX);
141 [ - + ]: 43 : if (!peer) {
142 : 0 : pr_err("Unix socket %#x without peer %#x\n",
143 : : ue.ino, ue.peer);
144 : 0 : goto err;
145 : : }
146 : :
147 : : /*
148 : : * Peer should have us as peer or have a name by which
149 : : * we can access one.
150 : : */
151 [ + + ]: 43 : if (peer->peer_ino != ue.ino) {
152 [ - + ]: 5 : if (!peer->name) {
153 : 0 : pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
154 : : ue.ino, ue.peer, peer->peer_ino, peer->name);
155 : 0 : goto err;
156 : : }
157 : :
158 : : /*
159 : : * It can be external socket, so we defer dumping
160 : : * until all sockets the program owns are processed.
161 : : */
162 [ + - ][ + + ]: 5 : if (!peer->sd.already_dumped && list_empty(&peer->list)) {
163 : 3 : show_one_unix("Add a peer", peer);
164 : 3 : list_add_tail(&peer->list, &unix_sockets);
165 : : }
166 : : }
167 : :
168 [ + + ][ + + ]: 43 : if ((ue.type != SOCK_DGRAM) && (
169 [ + - ]: 2 : ((ue.shutdown == SK_SHUTDOWN__READ) &&
170 [ + + ]: 20 : (peer->shutdown != SK_SHUTDOWN__WRITE)) ||
171 [ + - ]: 2 : ((ue.shutdown == SK_SHUTDOWN__WRITE) &&
172 [ + + ]: 20 : (peer->shutdown != SK_SHUTDOWN__READ)) ||
173 [ - + ]: 4 : ((ue.shutdown == SK_SHUTDOWN__BOTH) &&
174 : 4 : (peer->shutdown != SK_SHUTDOWN__BOTH)) )) {
175 : : /*
176 : : * On restore we assume, that stream pairs must
177 : : * be shut down from one end only
178 : : */
179 : 0 : pr_err("Shutdown mismatch %u:%d -> %u:%d\n",
180 : : ue.ino, ue.shutdown, peer->sd.ino, peer->shutdown);
181 : 0 : goto err;
182 : : }
183 [ + + ]: 14 : } else if (ue.state == TCP_ESTABLISHED) {
184 : : const struct unix_sk_listen_icon *e;
185 : :
186 : : /*
187 : : * If this is in-flight connection we need to figure
188 : : * out where to connect it on restore. Thus, tune up peer
189 : : * id by searching an existing listening socket.
190 : : *
191 : : * Note the socket name will be found at restore stage,
192 : : * not now, just to reduce size of dump files.
193 : : */
194 : :
195 : 4 : e = lookup_unix_listen_icons(ue.ino);
196 [ - + ]: 2 : if (!e) {
197 : 0 : pr_err("Dangling in-flight connection %d\n", ue.ino);
198 : 0 : goto err;
199 : : }
200 : :
201 : : /* e->sk_desc is _never_ NULL */
202 [ - + ]: 2 : if (e->sk_desc->state != TCP_LISTEN) {
203 : 0 : pr_err("In-flight connection on "
204 : : "non-listening socket %d\n", ue.ino);
205 : 0 : goto err;
206 : : }
207 : :
208 : 2 : ue.peer = e->sk_desc->sd.ino;
209 : :
210 : 2 : pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
211 : : ue.ino, ue.peer);
212 : : }
213 : :
214 [ + - ]: 57 : if (dump_socket_opts(lfd, &skopts))
215 : : goto err;
216 : :
217 [ + - ]: 57 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &ue, PB_UNIXSK))
218 : : goto err;
219 : :
220 [ + + ][ + + ]: 57 : if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
221 : : sk->state == TCP_LISTEN))
222 [ + - ]: 10 : if (dump_sk_queue(lfd, ue.id))
223 : : goto err;
224 : :
225 : 57 : pr_info("Dumping unix socket at %d\n", p->fd);
226 : 57 : show_one_unix("Dumping", sk);
227 : 57 : show_one_unix_img("Dumped", &ue);
228 : 57 : release_skopts(&skopts);
229 : :
230 : 57 : list_del_init(&sk->list);
231 : 57 : sk->sd.already_dumped = 1;
232 : :
233 : : return 0;
234 : :
235 : : err:
236 : 57 : release_skopts(&skopts);
237 : : return -1;
238 : : }
239 : :
240 : : static const struct fdtype_ops unix_dump_ops = {
241 : : .type = FD_TYPES__UNIXSK,
242 : : .dump = dump_one_unix_fd,
243 : : };
244 : :
245 : 57 : int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set)
246 : : {
247 : 57 : return do_dump_gen_file(p, lfd, &unix_dump_ops, set);
248 : : }
249 : :
250 : 4972 : static int unix_collect_one(const struct unix_diag_msg *m,
251 : : struct rtattr **tb)
252 : : {
253 : : struct unix_sk_desc *d;
254 : 4972 : char *name = NULL;
255 : 4972 : int ret = 0;
256 : :
257 [ - + ]: 4972 : d = xzalloc(sizeof(*d));
258 [ + - ]: 4972 : if (!d)
259 : : return -1;
260 : :
261 : 4972 : d->type = m->udiag_type;
262 : 4972 : d->state = m->udiag_state;
263 : 4972 : INIT_LIST_HEAD(&d->list);
264 : :
265 [ + - ]: 4972 : if (tb[UNIX_DIAG_SHUTDOWN])
266 : 4972 : d->shutdown = *(u8 *)RTA_DATA(tb[UNIX_DIAG_SHUTDOWN]);
267 : : else
268 [ # # ]: 0 : pr_err_once("No socket shutdown info\n");
269 : :
270 [ + + ]: 4972 : if (tb[UNIX_DIAG_PEER])
271 : 3867 : d->peer_ino = *(int *)RTA_DATA(tb[UNIX_DIAG_PEER]);
272 : :
273 [ + + ]: 4972 : if (tb[UNIX_DIAG_NAME]) {
274 : 2197 : int len = RTA_PAYLOAD(tb[UNIX_DIAG_NAME]);
275 : :
276 [ - + ]: 2197 : name = xmalloc(len + 1);
277 [ + - ]: 2197 : if (!name)
278 : : goto err;
279 : :
280 : 2197 : memcpy(name, RTA_DATA(tb[UNIX_DIAG_NAME]), len);
281 : 2197 : name[len] = '\0';
282 : :
283 [ + + ]: 2197 : if (name[0] != '\0') {
284 : : struct unix_diag_vfs *uv;
285 : : struct stat st;
286 : : char rpath[PATH_MAX];
287 : :
288 [ - + ]: 2195 : if (name[0] != '/') {
289 : 0 : pr_warn("Relative bind path '%s' "
290 : : "unsupported\n", name);
291 : : goto skip;
292 : : }
293 : :
294 [ - + ]: 2195 : if (!tb[UNIX_DIAG_VFS]) {
295 : 0 : pr_err("Bound socket w/o inode %d\n",
296 : : m->udiag_ino);
297 : : goto skip;
298 : : }
299 : :
300 : 2195 : uv = RTA_DATA(tb[UNIX_DIAG_VFS]);
301 : 2195 : snprintf(rpath, sizeof(rpath), ".%s", name);
302 [ + + ]: 2195 : if (fstatat(mntns_root, rpath, &st, 0)) {
303 : 24 : pr_perror("Can't stat socket %d(%s)",
304 : : m->udiag_ino, rpath);
305 : : goto skip;
306 : : }
307 : :
308 [ + + ][ - + ]: 2171 : if ((st.st_ino != uv->udiag_vfs_ino) ||
309 : 2081 : (st.st_dev != kdev_to_odev(uv->udiag_vfs_dev))) {
310 : 90 : pr_info("unix: Dropping path for "
311 : : "unlinked bound "
312 : : "sk %#x.%#x real %#x.%#x\n",
313 : : (int)st.st_dev,
314 : : (int)st.st_ino,
315 : : (int)uv->udiag_vfs_dev,
316 : : (int)uv->udiag_vfs_ino);
317 : : /*
318 : : * When a socket is bound to unlinked file, we
319 : : * just drop his name, since noone will access
320 : : * it via one.
321 : : */
322 [ + - ]: 2195 : xfree(name);
323 : : len = 0;
324 : : name = NULL;
325 : : }
326 : : }
327 : :
328 : 2173 : d->namelen = len;
329 : 2173 : d->name = name;
330 : : }
331 : :
332 [ + + ]: 4948 : if (tb[UNIX_DIAG_ICONS]) {
333 : 632 : int len = RTA_PAYLOAD(tb[UNIX_DIAG_ICONS]);
334 : : int i;
335 : :
336 [ - + ]: 632 : d->icons = xmalloc(len);
337 [ + - ]: 632 : if (!d->icons)
338 : : goto err;
339 : :
340 : 632 : memcpy(d->icons, RTA_DATA(tb[UNIX_DIAG_ICONS]), len);
341 : 632 : d->nr_icons = len / sizeof(u32);
342 : :
343 : : /*
344 : : * Remember these sockets, we will need them
345 : : * to fix up in-flight sockets peers.
346 : : */
347 [ + + ]: 634 : for (i = 0; i < d->nr_icons; i++) {
348 : : struct unix_sk_listen_icon *e, **chain;
349 : : int n;
350 : :
351 [ - + ]: 2 : e = xzalloc(sizeof(*e));
352 [ + - ]: 2 : if (!e)
353 : : goto err;
354 : :
355 : 2 : n = d->icons[i];
356 : 2 : chain = &unix_listen_icons[n % SK_HASH_SIZE];
357 : 2 : e->next = *chain;
358 : 2 : *chain = e;
359 : :
360 : 2 : pr_debug("\t\tCollected icon %d\n", d->icons[i]);
361 : :
362 : 2 : e->peer_ino = n;
363 : 2 : e->sk_desc = d;
364 : : }
365 : :
366 : :
367 : : }
368 : :
369 [ + - ]: 4948 : if (tb[UNIX_DIAG_RQLEN]) {
370 : : struct unix_diag_rqlen *rq;
371 : :
372 : 4948 : rq = (struct unix_diag_rqlen *)RTA_DATA(tb[UNIX_DIAG_RQLEN]);
373 : 4948 : d->rqlen = rq->udiag_rqueue;
374 : 4948 : d->wqlen = rq->udiag_wqueue;
375 : : }
376 : :
377 : 4948 : sk_collect_one(m->udiag_ino, AF_UNIX, &d->sd);
378 : 4948 : show_one_unix("Collected", d);
379 : :
380 : 4948 : return 0;
381 : : err:
382 : : ret = -1;
383 : : skip:
384 [ - + ]: 24 : xfree(d->icons);
385 [ + - ]: 24 : xfree(name);
386 [ + - ]: 24 : xfree(d);
387 : 4972 : return ret;
388 : : }
389 : :
390 : 4972 : int unix_receive_one(struct nlmsghdr *h, void *arg)
391 : : {
392 : 4972 : struct unix_diag_msg *m = NLMSG_DATA(h);
393 : : struct rtattr *tb[UNIX_DIAG_MAX+1];
394 : :
395 : 4972 : parse_rtattr(tb, UNIX_DIAG_MAX, (struct rtattr *)(m + 1),
396 : 4972 : h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
397 : :
398 : 4972 : return unix_collect_one(m, tb);
399 : : }
400 : :
401 : 166 : int fix_external_unix_sockets(void)
402 : : {
403 : : struct unix_sk_desc *sk;
404 : :
405 : 166 : pr_debug("Dumping external sockets\n");
406 : :
407 [ + + ]: 167 : list_for_each_entry(sk, &unix_sockets, list) {
408 : 1 : UnixSkEntry e = UNIX_SK_ENTRY__INIT;
409 : 1 : FownEntry fown = FOWN_ENTRY__INIT;
410 : 1 : SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
411 : :
412 : 1 : show_one_unix("Dumping extern", sk);
413 : :
414 [ - + ]: 1 : BUG_ON(sk->sd.already_dumped);
415 : :
416 [ - + ]: 1 : if (!opts.ext_unix_sk) {
417 : 0 : show_one_unix("Runaway socket", sk);
418 : : goto err;
419 : : }
420 : :
421 [ - + ]: 1 : if (sk->type != SOCK_DGRAM) {
422 : 0 : show_one_unix("Ext stream not supported", sk);
423 : : goto err;
424 : : }
425 : :
426 : 1 : e.id = fd_id_generate_special();
427 : 1 : e.ino = sk->sd.ino;
428 : 1 : e.type = SOCK_DGRAM;
429 : 1 : e.state = TCP_LISTEN;
430 : 1 : e.name.data = (void *)sk->name;
431 : 1 : e.name.len = (size_t)sk->namelen;
432 : 1 : e.uflags = USK_EXTERN;
433 : 1 : e.peer = 0;
434 : 1 : e.fown = &fown;
435 : 1 : e.opts = &skopts;
436 : :
437 [ + - ]: 1 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &e, PB_UNIXSK))
438 : : goto err;
439 : :
440 : 1 : show_one_unix_img("Dumped extern", &e);
441 : : }
442 : :
443 : : return 0;
444 : : err:
445 : 0 : return -1;
446 : : }
447 : :
448 : : struct unix_sk_info {
449 : : UnixSkEntry *ue;
450 : : struct list_head list;
451 : : char *name;
452 : : unsigned flags;
453 : : struct unix_sk_info *peer;
454 : : struct file_desc d;
455 : : futex_t bound;
456 : : };
457 : :
458 : : #define USK_PAIR_MASTER 0x1
459 : : #define USK_PAIR_SLAVE 0x2
460 : :
461 : : static struct unix_sk_info *find_unix_sk_by_ino(int ino)
462 : : {
463 : : struct unix_sk_info *ui;
464 : :
465 [ + - ]: 179 : list_for_each_entry(ui, &unix_sockets, list) {
466 [ + + ]: 179 : if (ui->ue->ino == ino)
467 : : return ui;
468 : : }
469 : :
470 : : return NULL;
471 : : }
472 : :
473 : 0 : void show_unixsk(int fd, struct cr_options *o)
474 : : {
475 : 0 : pb_show_plain_pretty(fd, PB_UNIXSK, "1:%#x 2:%#x 3:%d 4:%d 5:%d 6:%d 7:%d 8:%#x 11:S");
476 : 0 : }
477 : :
478 : 35 : static int shutdown_unix_sk(int sk, struct unix_sk_info *ui)
479 : : {
480 : : int how;
481 : 35 : UnixSkEntry *ue = ui->ue;
482 : :
483 [ + + ][ + - ]: 35 : if (!ue->has_shutdown || ue->shutdown == SK_SHUTDOWN__NONE)
484 : : return 0;
485 : :
486 : 20 : how = sk_decode_shutdown(ue->shutdown);
487 [ - + ]: 10 : if (shutdown(sk, how)) {
488 : 0 : pr_perror("Can't shutdown unix socket");
489 : : return -1;
490 : : }
491 : :
492 : 35 : pr_debug("Socket %#x is shut down %d\n", ue->ino, how);
493 : : return 0;
494 : : }
495 : :
496 : 57 : static int post_open_unix_sk(struct file_desc *d, int fd)
497 : : {
498 : : struct unix_sk_info *ui;
499 : : struct unix_sk_info *peer;
500 : : struct sockaddr_un addr;
501 : :
502 : 57 : ui = container_of(d, struct unix_sk_info, d);
503 [ + + ]: 57 : if (ui->flags & (USK_PAIR_MASTER | USK_PAIR_SLAVE))
504 : : return 0;
505 : :
506 : 21 : peer = ui->peer;
507 : :
508 [ + + ]: 21 : if (peer == NULL)
509 : : return 0;
510 : :
511 : 9 : pr_info("\tConnect %#x to %#x\n", ui->ue->ino, peer->ue->ino);
512 : :
513 : : /* Skip external sockets */
514 [ + + ]: 9 : if (!list_empty(&peer->d.fd_info_head))
515 : 8 : futex_wait_while(&peer->bound, 0);
516 : :
517 : 9 : memset(&addr, 0, sizeof(addr));
518 : 9 : addr.sun_family = AF_UNIX;
519 : 9 : memcpy(&addr.sun_path, peer->name, peer->ue->name.len);
520 : :
521 [ - + ]: 9 : if (connect(fd, (struct sockaddr *)&addr,
522 : : sizeof(addr.sun_family) +
523 : 9 : peer->ue->name.len) < 0) {
524 : 0 : pr_perror("Can't connect %#x socket", ui->ue->ino);
525 : : return -1;
526 : : }
527 : :
528 [ + - ]: 9 : if (restore_sk_queue(fd, peer->ue->id))
529 : : return -1;
530 : :
531 [ + - ]: 9 : if (rst_file_params(fd, ui->ue->fown, ui->ue->flags))
532 : : return -1;
533 : :
534 [ + - ]: 9 : if (restore_socket_opts(fd, ui->ue->opts))
535 : : return -1;
536 : :
537 [ + - ]: 57 : if (shutdown_unix_sk(fd, ui))
538 : : return -1;
539 : :
540 : : return 0;
541 : : }
542 : :
543 : 57 : static int bind_unix_sk(int sk, struct unix_sk_info *ui)
544 : : {
545 : : struct sockaddr_un addr;
546 : :
547 [ + + ]: 57 : if ((ui->ue->type == SOCK_STREAM) && (ui->ue->state == TCP_ESTABLISHED))
548 : : /*
549 : : * FIXME this can be done, but for doing this properly we
550 : : * need to bind socket to its name, then rename one to
551 : : * some temporary unique one and after all the sockets are
552 : : * restored we should walk those temp names and rename
553 : : * some of them back to real ones.
554 : : */
555 : : goto done;
556 : :
557 : 35 : memset(&addr, 0, sizeof(addr));
558 : 35 : addr.sun_family = AF_UNIX;
559 : 35 : memcpy(&addr.sun_path, ui->name, ui->ue->name.len);
560 : :
561 [ - + ]: 35 : if (bind(sk, (struct sockaddr *)&addr,
562 : 35 : sizeof(addr.sun_family) + ui->ue->name.len)) {
563 : 0 : pr_perror("Can't bind socket");
564 : : return -1;
565 : : }
566 : :
567 : 57 : futex_set_and_wake(&ui->bound, 1);
568 : : done:
569 : : return 0;
570 : : }
571 : :
572 : 57 : static int unixsk_should_open_transport(FdinfoEntry *fe,
573 : : struct file_desc *d)
574 : : {
575 : : struct unix_sk_info *ui;
576 : :
577 : 57 : ui = container_of(d, struct unix_sk_info, d);
578 : 57 : return ui->flags & USK_PAIR_SLAVE;
579 : : }
580 : :
581 : 18 : static int open_unixsk_pair_master(struct unix_sk_info *ui)
582 : : {
583 : : int sk[2], tsk;
584 : 18 : struct unix_sk_info *peer = ui->peer;
585 : : struct fdinfo_list_entry *fle;
586 : :
587 : 18 : pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
588 : : ui->ue->id, ui->ue->ino, ui->ue->peer);
589 : :
590 [ - + ]: 18 : if (socketpair(PF_UNIX, ui->ue->type, 0, sk) < 0) {
591 : 0 : pr_perror("Can't make socketpair");
592 : : return -1;
593 : : }
594 : :
595 [ + - ]: 18 : if (restore_sk_queue(sk[0], peer->ue->id))
596 : : return -1;
597 [ + - ]: 18 : if (restore_sk_queue(sk[1], ui->ue->id))
598 : : return -1;
599 : :
600 [ + - ]: 18 : if (bind_unix_sk(sk[0], ui))
601 : : return -1;
602 : :
603 [ + - ]: 18 : if (rst_file_params(sk[0], ui->ue->fown, ui->ue->flags))
604 : : return -1;
605 : :
606 [ + - ]: 18 : if (restore_socket_opts(sk[0], ui->ue->opts))
607 : : return -1;
608 : :
609 [ + - ]: 18 : if (shutdown_unix_sk(sk[0], ui))
610 : : return -1;
611 : :
612 : 18 : tsk = socket(PF_UNIX, SOCK_DGRAM, 0);
613 [ - + ]: 18 : if (tsk < 0) {
614 : 0 : pr_perror("Can't make transport socket");
615 : : return -1;
616 : : }
617 : :
618 : 18 : fle = file_master(&peer->d);
619 [ - + ]: 18 : if (send_fd_to_peer(sk[1], fle, tsk)) {
620 : 0 : pr_err("Can't send pair slave\n");
621 : : return -1;
622 : : }
623 : :
624 : 18 : close(tsk);
625 : 18 : close(sk[1]);
626 : :
627 : 18 : return sk[0];
628 : : }
629 : :
630 : 18 : static int open_unixsk_pair_slave(struct unix_sk_info *ui)
631 : : {
632 : : struct fdinfo_list_entry *fle;
633 : : int sk;
634 : :
635 : 18 : fle = file_master(&ui->d);
636 : :
637 : 18 : pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
638 : : ui->ue->id, ui->ue->ino, ui->ue->peer, fle->fe->fd);
639 : :
640 : 18 : sk = recv_fd(fle->fe->fd);
641 [ - + ]: 18 : if (sk < 0) {
642 : 0 : pr_err("Can't recv pair slave");
643 : 0 : return -1;
644 : : }
645 : 18 : close(fle->fe->fd);
646 : :
647 [ + - ]: 18 : if (bind_unix_sk(sk, ui))
648 : : return -1;
649 : :
650 [ + - ]: 18 : if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
651 : : return -1;
652 : :
653 [ + - ]: 18 : if (restore_socket_opts(sk, ui->ue->opts))
654 : : return -1;
655 : :
656 [ + + ]: 18 : if (ui->ue->type == SOCK_DGRAM)
657 : : /*
658 : : * Stream socket's "slave" end will be shut down
659 : : * together with master
660 : : */
661 [ + - ]: 8 : if (shutdown_unix_sk(sk, ui))
662 : : return -1;
663 : :
664 : 18 : return sk;
665 : : }
666 : :
667 : 21 : static int open_unixsk_standalone(struct unix_sk_info *ui)
668 : : {
669 : : int sk;
670 : :
671 : 21 : pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
672 : : ui->ue->id, ui->ue->ino, ui->ue->peer);
673 : :
674 : 21 : sk = socket(PF_UNIX, ui->ue->type, 0);
675 [ - + ]: 21 : if (sk < 0) {
676 : 0 : pr_perror("Can't make unix socket");
677 : 0 : return -1;
678 : : }
679 : :
680 [ + - ]: 21 : if (bind_unix_sk(sk, ui))
681 : : return -1;
682 : :
683 [ + + ]: 21 : if (ui->ue->state == TCP_LISTEN) {
684 : 2 : pr_info("\tPutting %#x into listen state\n", ui->ue->ino);
685 [ - + ]: 2 : if (listen(sk, ui->ue->backlog) < 0) {
686 : 0 : pr_perror("Can't make usk listen");
687 : 0 : return -1;
688 : : }
689 : : }
690 : :
691 [ + - ]: 21 : if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
692 : : return -1;
693 : :
694 [ + - ]: 21 : if (restore_socket_opts(sk, ui->ue->opts))
695 : : return -1;
696 : :
697 : 21 : return sk;
698 : : }
699 : :
700 : 57 : static int open_unix_sk(struct file_desc *d)
701 : : {
702 : : struct unix_sk_info *ui;
703 : :
704 : 57 : ui = container_of(d, struct unix_sk_info, d);
705 [ + + ]: 57 : if (ui->flags & USK_PAIR_MASTER)
706 : 18 : return open_unixsk_pair_master(ui);
707 [ + + ]: 39 : else if (ui->flags & USK_PAIR_SLAVE)
708 : 18 : return open_unixsk_pair_slave(ui);
709 : : else
710 : 57 : return open_unixsk_standalone(ui);
711 : : }
712 : :
713 : : static struct file_desc_ops unix_desc_ops = {
714 : : .type = FD_TYPES__UNIXSK,
715 : : .open = open_unix_sk,
716 : : .post_open = post_open_unix_sk,
717 : : .want_transport = unixsk_should_open_transport,
718 : : };
719 : :
720 : 86 : static int collect_one_unixsk(void *o, ProtobufCMessage *base)
721 : : {
722 : 86 : struct unix_sk_info *ui = o;
723 : :
724 : 86 : ui->ue = pb_msg(base, UnixSkEntry);
725 : :
726 [ + + ]: 86 : if (ui->ue->name.len) {
727 [ - + ]: 19 : if (ui->ue->name.len >= UNIX_PATH_MAX) {
728 : 0 : pr_err("Bad unix name len %d\n", (int)ui->ue->name.len);
729 : 0 : return -1;
730 : : }
731 : :
732 : 19 : ui->name = (void *)ui->ue->name.data;
733 : :
734 : : /*
735 : : * Make FS clean from sockets we're about to
736 : : * restore. See for how we bind them for details
737 : : */
738 [ + + ][ + + ]: 19 : if (ui->name[0] != '\0' &&
739 : 16 : !(ui->ue->uflags & USK_EXTERN))
740 : 15 : unlink(ui->name);
741 : : } else
742 : 67 : ui->name = NULL;
743 : :
744 : 86 : futex_init(&ui->bound);
745 : 86 : ui->peer = NULL;
746 : 86 : ui->flags = 0;
747 : 86 : pr_info(" `- Got %#x peer %#x\n", ui->ue->ino, ui->ue->peer);
748 : 86 : file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops);
749 : 86 : list_add_tail(&ui->list, &unix_sockets);
750 : :
751 : 86 : return 0;
752 : : }
753 : :
754 : 355 : int collect_unix_sockets(void)
755 : : {
756 : : int ret;
757 : :
758 : 355 : pr_info("Reading unix sockets in\n");
759 : :
760 : 355 : ret = collect_image_sh(CR_FD_UNIXSK, PB_UNIXSK,
761 : : sizeof(struct unix_sk_info), collect_one_unixsk);
762 [ + - ]: 355 : if (!ret)
763 : 355 : ret = read_sk_queues();
764 : :
765 : 355 : return 0;
766 : : }
767 : :
768 : 355 : int resolve_unix_peers(void)
769 : : {
770 : : struct unix_sk_info *ui, *peer;
771 : : struct fdinfo_list_entry *fle, *fle_peer;
772 : :
773 [ + + ]: 441 : list_for_each_entry(ui, &unix_sockets, list) {
774 [ + + ]: 86 : if (ui->peer)
775 : 27 : continue;
776 [ + + ]: 59 : if (!ui->ue->peer)
777 : 19 : continue;
778 : :
779 : 80 : peer = find_unix_sk_by_ino(ui->ue->peer);
780 : :
781 : : /*
782 : : * Connect to external sockets requires
783 : : * special option to be passed.
784 : : */
785 [ + - ][ + + ]: 40 : if (peer &&
786 [ - + ]: 1 : (peer->ue->uflags & USK_EXTERN) &&
787 : 1 : !(opts.ext_unix_sk))
788 : 0 : peer = NULL;
789 : :
790 [ - + ]: 40 : if (!peer) {
791 : 0 : pr_err("FATAL: Peer %#x unresolved for %#x\n",
792 : : ui->ue->peer, ui->ue->ino);
793 : 0 : return -1;
794 : : }
795 : :
796 : 40 : ui->peer = peer;
797 [ + + ]: 40 : if (ui == peer)
798 : : /* socket connected to self %) */
799 : 3 : continue;
800 [ + + ]: 37 : if (peer->ue->peer != ui->ue->ino)
801 : 10 : continue;
802 : :
803 : : /* socketpair or interconnected sockets */
804 : 27 : peer->peer = ui;
805 : :
806 : : /*
807 : : * Select who will restore the pair. Check is identical to
808 : : * the one in pipes.c and makes sure tasks wait for each other
809 : : * in pids sorting order (ascending).
810 : : */
811 : :
812 : 27 : fle = file_master(&ui->d);
813 : 27 : fle_peer = file_master(&peer->d);
814 : :
815 [ + - ]: 27 : if (fdinfo_rst_prio(fle, fle_peer)) {
816 : 27 : ui->flags |= USK_PAIR_MASTER;
817 : 27 : peer->flags |= USK_PAIR_SLAVE;
818 : : } else {
819 : 0 : peer->flags |= USK_PAIR_MASTER;
820 : 0 : ui->flags |= USK_PAIR_SLAVE;
821 : : }
822 : : }
823 : :
824 : 355 : pr_info("Unix sockets:\n");
825 [ + + ]: 441 : list_for_each_entry(ui, &unix_sockets, list) {
826 : : struct fdinfo_list_entry *fle;
827 : :
828 [ + + ]: 86 : pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue->ino, ui->ue->peer,
829 : : ui->peer ? ui->peer->ue->ino : 0, ui->flags);
830 [ + + ]: 171 : list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
831 : 85 : pr_info("\t\tfd %d in pid %d\n",
832 : : fle->fe->fd, fle->pid);
833 : :
834 : : }
835 : :
836 : : return 0;
837 : 195 : }
838 : :
|