clang-tidy: add Chrome-inspired checks
[lttng-tools.git] / src / common / unix.cpp
1 /*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-only
6 *
7 */
8
9 #define _LGPL_SOURCE
10 #include "unix.hpp"
11
12 #include <common/common.hpp>
13 #include <common/compat/errno.hpp>
14 #include <common/fd-handle.hpp>
15 #include <common/sessiond-comm/sessiond-comm.hpp>
16
17 #include <limits.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 /*
26 * Connect to unix socket using the path name.
27 */
28 int lttcomm_connect_unix_sock(const char *pathname)
29 {
30 struct sockaddr_un s_un;
31 int fd, ret, closeret;
32
33 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
34 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
35 pathname,
36 strlen(pathname) + 1,
37 sizeof(s_un.sun_path));
38 ret = -ENAMETOOLONG;
39 goto error;
40 }
41
42 fd = socket(PF_UNIX, SOCK_STREAM, 0);
43 if (fd < 0) {
44 PERROR("socket");
45 ret = fd;
46 goto error;
47 }
48
49 memset(&s_un, 0, sizeof(s_un));
50 s_un.sun_family = AF_UNIX;
51 strncpy(s_un.sun_path, pathname, sizeof(s_un.sun_path));
52 s_un.sun_path[sizeof(s_un.sun_path) - 1] = '\0';
53
54 ret = connect(fd, (struct sockaddr *) &s_un, sizeof(s_un));
55 if (ret < 0) {
56 /*
57 * Don't print message on connect error, because connect is used in
58 * normal execution to detect if sessiond is alive.
59 */
60 goto error_connect;
61 }
62
63 return fd;
64
65 error_connect:
66 closeret = close(fd);
67 if (closeret) {
68 PERROR("close");
69 }
70 error:
71 return ret;
72 }
73
74 /*
75 * Do an accept(2) on the sock and return the new file descriptor. The socket
76 * MUST be bind(2) before.
77 */
78 int lttcomm_accept_unix_sock(int sock)
79 {
80 int new_fd;
81 struct sockaddr_un s_un;
82 socklen_t len = sizeof(s_un);
83
84 /* Blocking call */
85 new_fd = accept(sock, (struct sockaddr *) &s_un, &len);
86 if (new_fd < 0) {
87 PERROR("accept");
88 }
89
90 return new_fd;
91 }
92
93 int lttcomm_create_anon_unix_socketpair(int *fds)
94 {
95 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fds) < 0) {
96 PERROR("socketpair");
97 return -1;
98 }
99 return 0;
100 }
101
102 /*
103 * Creates a AF_UNIX local socket using pathname bind the socket upon creation
104 * and return the fd.
105 */
106 int lttcomm_create_unix_sock(const char *pathname)
107 {
108 struct sockaddr_un s_un;
109 int fd = -1;
110 int ret = -1;
111
112 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
113 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
114 pathname,
115 strlen(pathname) + 1,
116 sizeof(s_un.sun_path));
117 ret = -ENAMETOOLONG;
118 goto error;
119 }
120
121 /* Create server socket */
122 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
123 PERROR("socket");
124 goto error;
125 }
126
127 memset(&s_un, 0, sizeof(s_un));
128 s_un.sun_family = AF_UNIX;
129 strncpy(s_un.sun_path, pathname, sizeof(s_un.sun_path));
130 s_un.sun_path[sizeof(s_un.sun_path) - 1] = '\0';
131
132 /* Unlink the old file if present */
133 (void) unlink(pathname);
134 ret = bind(fd, (struct sockaddr *) &s_un, sizeof(s_un));
135 if (ret < 0) {
136 PERROR("bind");
137 goto error;
138 }
139
140 return fd;
141
142 error:
143 if (fd >= 0) {
144 if (close(fd) < 0) {
145 PERROR("close create unix sock");
146 }
147 }
148 return ret;
149 }
150
151 /*
152 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
153 */
154 int lttcomm_listen_unix_sock(int sock)
155 {
156 int ret;
157
158 ret = listen(sock, LTTNG_SESSIOND_COMM_MAX_LISTEN);
159 if (ret < 0) {
160 PERROR("listen");
161 }
162
163 return ret;
164 }
165
166 /*
167 * Receive data of size len in put that data into the buf param. Using recvmsg
168 * API.
169 *
170 * Return the size of received data.
171 */
172 ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len)
173 {
174 struct msghdr msg;
175 struct iovec iov[1];
176 ssize_t ret = -1;
177 size_t len_last;
178
179 LTTNG_ASSERT(sock);
180 LTTNG_ASSERT(buf);
181 LTTNG_ASSERT(len > 0);
182
183 memset(&msg, 0, sizeof(msg));
184
185 iov[0].iov_base = buf;
186 iov[0].iov_len = len;
187 msg.msg_iov = iov;
188 msg.msg_iovlen = 1;
189
190 do {
191 len_last = iov[0].iov_len;
192 ret = lttng_recvmsg_nosigpipe(sock, &msg);
193 if (ret > 0) {
194 iov[0].iov_base = (char *) iov[0].iov_base + ret;
195 iov[0].iov_len -= ret;
196 LTTNG_ASSERT(ret <= len_last);
197 }
198 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
199 if (ret < 0) {
200 PERROR("recvmsg");
201 } else if (ret > 0) {
202 ret = len;
203 }
204 /* Else ret = 0 meaning an orderly shutdown. */
205
206 return ret;
207 }
208
209 /*
210 * Receive data of size len in put that data into the buf param. Using recvmsg
211 * API. Only use with sockets set in non-blocking mode.
212 *
213 * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a
214 * poll set. The poll loop will handle the EPIPE original cause.
215 *
216 * Return the size of received data.
217 */
218 ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len)
219 {
220 struct msghdr msg;
221 struct iovec iov[1];
222 ssize_t ret;
223
224 LTTNG_ASSERT(sock);
225 LTTNG_ASSERT(buf);
226 LTTNG_ASSERT(len > 0);
227
228 memset(&msg, 0, sizeof(msg));
229
230 iov[0].iov_base = buf;
231 iov[0].iov_len = len;
232 msg.msg_iov = iov;
233 msg.msg_iovlen = 1;
234
235 retry:
236 ret = lttng_recvmsg_nosigpipe(sock, &msg);
237 if (ret < 0) {
238 if (errno == EINTR) {
239 goto retry;
240 } else {
241 /*
242 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
243 */
244 DIAGNOSTIC_PUSH
245 DIAGNOSTIC_IGNORE_LOGICAL_OP
246 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EPIPE) {
247 DIAGNOSTIC_POP
248 /*
249 * Nothing was recv.
250 */
251 ret = 0;
252 goto end;
253 }
254
255 /* Unexpected error */
256 PERROR("recvmsg");
257 ret = -1;
258 goto end;
259 }
260 }
261
262 end:
263 return ret;
264 }
265
266 /*
267 * Send buf data of size len. Using sendmsg API.
268 *
269 * Return the size of sent data.
270 */
271 ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len)
272 {
273 struct msghdr msg;
274 struct iovec iov[1];
275 ssize_t ret;
276
277 LTTNG_ASSERT(sock);
278 LTTNG_ASSERT(buf);
279 LTTNG_ASSERT(len > 0);
280
281 memset(&msg, 0, sizeof(msg));
282
283 iov[0].iov_base = (void *) buf;
284 iov[0].iov_len = len;
285 msg.msg_iov = iov;
286 msg.msg_iovlen = 1;
287
288 while (iov[0].iov_len) {
289 ret = sendmsg(sock, &msg, 0);
290 if (ret < 0) {
291 if (errno == EINTR) {
292 continue;
293 } else {
294 /*
295 * Only warn about EPIPE when quiet mode is
296 * deactivated.
297 * We consider EPIPE as expected.
298 */
299 if (errno != EPIPE || !lttng_opt_quiet) {
300 PERROR("sendmsg");
301 }
302 goto end;
303 }
304 }
305 iov[0].iov_len -= ret;
306 iov[0].iov_base = (char *) iov[0].iov_base + ret;
307 }
308 ret = len;
309 end:
310 return ret;
311 }
312
313 /*
314 * Send buf data of size len. Using sendmsg API.
315 * Only use with non-blocking sockets. The difference with the blocking version
316 * of the function is that this one does not retry to send on partial sends,
317 * except if the interruption was caused by a signal (EINTR).
318 *
319 * NOTE: EPIPE errors are NOT reported. This call expects the socket to be in a
320 * poll set. The poll loop will handle the EPIPE original cause.
321 *
322 * Return the size of sent data.
323 */
324 ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len)
325 {
326 struct msghdr msg;
327 struct iovec iov[1];
328 ssize_t ret;
329
330 LTTNG_ASSERT(sock);
331 LTTNG_ASSERT(buf);
332 LTTNG_ASSERT(len > 0);
333
334 memset(&msg, 0, sizeof(msg));
335
336 iov[0].iov_base = (void *) buf;
337 iov[0].iov_len = len;
338 msg.msg_iov = iov;
339 msg.msg_iovlen = 1;
340
341 retry:
342 ret = sendmsg(sock, &msg, 0);
343 if (ret < 0) {
344 if (errno == EINTR) {
345 goto retry;
346 } else {
347 /*
348 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
349 */
350 DIAGNOSTIC_PUSH
351 DIAGNOSTIC_IGNORE_LOGICAL_OP
352 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EPIPE) {
353 DIAGNOSTIC_POP
354 /*
355 * This can happen in non blocking mode.
356 * Nothing was sent.
357 */
358 ret = 0;
359 goto end;
360 }
361
362 /* Unexpected error */
363 PERROR("sendmsg");
364 ret = -1;
365 goto end;
366 }
367 }
368 end:
369 return ret;
370 }
371
372 /*
373 * Shutdown cleanly a unix socket.
374 */
375 int lttcomm_close_unix_sock(int sock)
376 {
377 int ret, closeret;
378
379 /* Shutdown receptions and transmissions */
380 ret = shutdown(sock, SHUT_RDWR);
381 if (ret < 0) {
382 /*
383 * The socket is already disconnected, don't error out.
384 * This doesn't happen on Linux, but it does on FreeBSD, see:
385 * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=227259
386 */
387 if (errno == ENOTCONN) {
388 ret = 0;
389 } else {
390 PERROR("shutdown");
391 }
392 }
393
394 closeret = close(sock);
395 if (closeret) {
396 PERROR("close");
397 }
398
399 return ret;
400 }
401
402 /*
403 * Send a message accompanied by fd(s) over a unix socket.
404 *
405 * Returns the size of data sent, or negative error value.
406 */
407 ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd)
408 {
409 struct msghdr msg;
410 struct cmsghdr *cmptr;
411 struct iovec iov[1];
412 ssize_t ret = -1;
413 unsigned int sizeof_fds = nb_fd * sizeof(int);
414 char tmp[CMSG_SPACE(sizeof_fds)];
415 char dummy = 0;
416
417 LTTNG_ASSERT(sock);
418 LTTNG_ASSERT(fds);
419 LTTNG_ASSERT(nb_fd > 0);
420
421 memset(&msg, 0, sizeof(msg));
422 memset(tmp, 0, sizeof(tmp));
423
424 if (nb_fd > LTTCOMM_MAX_SEND_FDS)
425 return -EINVAL;
426
427 msg.msg_control = (caddr_t) tmp;
428 msg.msg_controllen = CMSG_LEN(sizeof_fds);
429
430 cmptr = CMSG_FIRSTHDR(&msg);
431 if (!cmptr) {
432 return -1;
433 }
434
435 cmptr->cmsg_level = SOL_SOCKET;
436 cmptr->cmsg_type = SCM_RIGHTS;
437 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
438 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
439 /* Sum of the length of all control messages in the buffer: */
440 msg.msg_controllen = cmptr->cmsg_len;
441
442 iov[0].iov_base = &dummy;
443 iov[0].iov_len = 1;
444 msg.msg_iov = iov;
445 msg.msg_iovlen = 1;
446
447 do {
448 ret = sendmsg(sock, &msg, 0);
449 } while (ret < 0 && errno == EINTR);
450 if (ret < 0) {
451 /*
452 * Only warn about EPIPE when quiet mode is deactivated.
453 * We consider EPIPE as expected.
454 */
455 if (errno != EPIPE || !lttng_opt_quiet) {
456 PERROR("sendmsg");
457 }
458 }
459 return ret;
460 }
461
462 /*
463 * Send the fd(s) of a payload view over a unix socket.
464 *
465 * Returns the size of data sent, or negative error value.
466 */
467 static ssize_t
468 _lttcomm_send_payload_view_fds_unix_sock(int sock, struct lttng_payload_view *view, bool blocking)
469 {
470 int i;
471 ssize_t ret;
472 struct lttng_dynamic_array raw_fds;
473 const int fd_count = lttng_payload_view_get_fd_handle_count(view);
474
475 lttng_dynamic_array_init(&raw_fds, sizeof(int), nullptr);
476
477 if (fd_count < 0) {
478 ret = -LTTNG_ERR_INVALID;
479 goto end;
480 }
481
482 /*
483 * Prepare a contiguous array of file descriptors to send them.
484 *
485 * Note that the reference to each fd is released during the iteration;
486 * we're just getting the numerical value of the fds to conform to the
487 * syscall's interface. We rely on the fact that "view" must remain
488 * valid for the duration of the call and that the underlying payload
489 * owns a reference to the fd_handles.
490 */
491 for (i = 0; i < fd_count; i++) {
492 struct fd_handle *handle = lttng_payload_view_pop_fd_handle(view);
493 const int raw_fd = fd_handle_get_fd(handle);
494 const int add_ret = lttng_dynamic_array_add_element(&raw_fds, &raw_fd);
495
496 fd_handle_put(handle);
497 if (add_ret) {
498 ret = -LTTNG_ERR_NOMEM;
499 goto end;
500 }
501 }
502
503 if (blocking) {
504 ret = lttcomm_send_fds_unix_sock(sock, (const int *) raw_fds.buffer.data, fd_count);
505 } else {
506 ret = lttcomm_send_fds_unix_sock_non_block(
507 sock, (const int *) raw_fds.buffer.data, fd_count);
508 }
509
510 end:
511 lttng_dynamic_array_reset(&raw_fds);
512 return ret;
513 }
514
515 ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock, struct lttng_payload_view *view)
516 {
517 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true);
518 }
519
520 ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock, struct lttng_payload_view *view)
521 {
522 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false);
523 }
524
525 /*
526 * Send a message accompanied by fd(s) over a unix socket.
527 * Only use for non blocking socket.
528 *
529 * Returns the size of data sent, or negative error value.
530 */
531 ssize_t lttcomm_send_fds_unix_sock_non_block(int sock, const int *fds, size_t nb_fd)
532 {
533 struct msghdr msg;
534 struct cmsghdr *cmptr;
535 struct iovec iov[1];
536 ssize_t ret = -1;
537 unsigned int sizeof_fds = nb_fd * sizeof(int);
538 char tmp[CMSG_SPACE(sizeof_fds)];
539 char dummy = 0;
540
541 LTTNG_ASSERT(sock);
542 LTTNG_ASSERT(fds);
543 LTTNG_ASSERT(nb_fd > 0);
544
545 memset(&msg, 0, sizeof(msg));
546 memset(tmp, 0, sizeof(tmp));
547
548 if (nb_fd > LTTCOMM_MAX_SEND_FDS)
549 return -EINVAL;
550
551 msg.msg_control = (caddr_t) tmp;
552 msg.msg_controllen = CMSG_LEN(sizeof_fds);
553
554 cmptr = CMSG_FIRSTHDR(&msg);
555 if (!cmptr) {
556 return -1;
557 }
558
559 cmptr->cmsg_level = SOL_SOCKET;
560 cmptr->cmsg_type = SCM_RIGHTS;
561 cmptr->cmsg_len = CMSG_LEN(sizeof_fds);
562 memcpy(CMSG_DATA(cmptr), fds, sizeof_fds);
563 /* Sum of the length of all control messages in the buffer: */
564 msg.msg_controllen = cmptr->cmsg_len;
565
566 iov[0].iov_base = &dummy;
567 iov[0].iov_len = 1;
568 msg.msg_iov = iov;
569 msg.msg_iovlen = 1;
570
571 retry:
572 ret = sendmsg(sock, &msg, 0);
573 if (ret < 0) {
574 if (errno == EINTR) {
575 goto retry;
576 } else {
577 /*
578 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
579 */
580 DIAGNOSTIC_PUSH
581 DIAGNOSTIC_IGNORE_LOGICAL_OP
582 if (errno == EAGAIN || errno == EWOULDBLOCK) {
583 DIAGNOSTIC_POP
584 /*
585 * This can happen in non blocking mode.
586 * Nothing was sent.
587 */
588 ret = 0;
589 goto end;
590 }
591
592 if (errno == EPIPE) {
593 /* Expected error, pass error to caller */
594 DBG3("EPIPE on sendmsg");
595 ret = -1;
596 goto end;
597 }
598
599 /* Unexpected error */
600 PERROR("sendmsg");
601 ret = -1;
602 goto end;
603 }
604 }
605
606 end:
607 return ret;
608 }
609
610 /*
611 * Recv a message accompanied by fd(s) from a unix socket.
612 *
613 * Returns the size of received data, or negative error value.
614 *
615 * Expect at most "nb_fd" file descriptors. Returns the number of fd
616 * actually received in nb_fd.
617 */
618 ssize_t lttcomm_recv_fds_unix_sock(int sock, int *fds, size_t nb_fd)
619 {
620 struct iovec iov[1];
621 ssize_t ret = 0;
622 struct cmsghdr *cmsg;
623 size_t sizeof_fds = nb_fd * sizeof(int);
624
625 #ifdef __linux__
626 /* Account for the struct ucred cmsg in the buffer size */
627 #define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred))
628 #else
629 #define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds)
630 #endif /* __linux__ */
631
632 char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE];
633 struct msghdr msg;
634 char dummy;
635
636 LTTNG_ASSERT(sock);
637 LTTNG_ASSERT(fds);
638 LTTNG_ASSERT(nb_fd > 0);
639
640 memset(&msg, 0, sizeof(msg));
641
642 /* Prepare to receive the structures */
643 iov[0].iov_base = &dummy;
644 iov[0].iov_len = 1;
645 msg.msg_iov = iov;
646 msg.msg_iovlen = 1;
647
648 cmsg = (struct cmsghdr *) recv_buf;
649 cmsg->cmsg_len = CMSG_LEN(sizeof_fds);
650 cmsg->cmsg_level = SOL_SOCKET;
651 cmsg->cmsg_type = SCM_RIGHTS;
652
653 msg.msg_control = cmsg;
654 msg.msg_controllen = CMSG_LEN(sizeof(recv_buf));
655 msg.msg_flags = 0;
656
657 retry:
658 ret = lttng_recvmsg_nosigpipe(sock, &msg);
659 if (ret < 0) {
660 if (errno == EINTR) {
661 goto retry;
662 } else {
663 /* We consider EPIPE and EAGAIN as expected. */
664 if (!lttng_opt_quiet && (errno != EPIPE && errno != EAGAIN)) {
665 PERROR("recvmsg");
666 }
667 goto end;
668 }
669 }
670
671 if (ret != 1) {
672 fprintf(stderr, "Error: Received %zd bytes, expected %d\n", ret, 1);
673 goto end;
674 }
675
676 if (msg.msg_flags & MSG_CTRUNC) {
677 fprintf(stderr, "Error: Control message truncated.\n");
678 ret = -1;
679 goto end;
680 }
681
682 /*
683 * If the socket was configured with SO_PASSCRED, the kernel will add a
684 * control message (cmsg) to the ancillary data of the unix socket. We
685 * need to expect a cmsg of the SCM_CREDENTIALS as the first control
686 * message.
687 */
688 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
689 if (cmsg->cmsg_level != SOL_SOCKET) {
690 fprintf(stderr, "Error: The socket needs to be of type SOL_SOCKET\n");
691 ret = -1;
692 goto end;
693 }
694 if (cmsg->cmsg_type == SCM_RIGHTS) {
695 /*
696 * We found the controle message for file descriptors,
697 * now copy the fds to the fds ptr and return success.
698 */
699 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
700 fprintf(stderr,
701 "Error: Received %zu bytes of"
702 "ancillary data for FDs, expected %zu\n",
703 (size_t) cmsg->cmsg_len,
704 (size_t) CMSG_LEN(sizeof_fds));
705 ret = -1;
706 goto end;
707 }
708 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
709 ret = sizeof_fds;
710 goto end;
711 }
712 #ifdef __linux__
713 if (cmsg->cmsg_type == SCM_CREDENTIALS) {
714 /*
715 * Expect credentials to be sent when expecting fds even
716 * if no credential were include in the send(). The
717 * kernel adds them...
718 */
719 ret = -1;
720 }
721 #endif /* __linux__ */
722 }
723 end:
724 return ret;
725 }
726
727 static void close_raw_fd(void *ptr)
728 {
729 const int raw_fd = *((const int *) ptr);
730
731 if (raw_fd >= 0) {
732 const int ret = close(raw_fd);
733
734 if (ret) {
735 PERROR("Failed to close file descriptor %d", raw_fd);
736 }
737 }
738 }
739
740 static enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds,
741 struct lttng_payload *payload)
742 {
743 int i;
744 enum lttng_error_code ret_code = LTTNG_OK;
745 const int fd_count = lttng_dynamic_array_get_count(raw_fds);
746
747 for (i = 0; i < fd_count; i++) {
748 int ret;
749 struct fd_handle *handle;
750 int *raw_fd = (int *) lttng_dynamic_array_get_element(raw_fds, i);
751
752 LTTNG_ASSERT(*raw_fd != -1);
753
754 handle = fd_handle_create(*raw_fd);
755 if (!handle) {
756 ret_code = LTTNG_ERR_NOMEM;
757 goto end;
758 }
759
760 /* FD ownership transferred to the handle. */
761 *raw_fd = -1;
762
763 ret = lttng_payload_push_fd_handle(payload, handle);
764 fd_handle_put(handle);
765 if (ret) {
766 ret_code = LTTNG_ERR_NOMEM;
767 goto end;
768 }
769 }
770
771 end:
772 return ret_code;
773 }
774
775 static ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock,
776 size_t nb_fd,
777 struct lttng_payload *payload,
778 bool blocking)
779 {
780 int i = 0;
781 enum lttng_error_code add_ret;
782 ssize_t ret;
783 int default_value = -1;
784 struct lttng_dynamic_array raw_fds;
785
786 LTTNG_ASSERT(sock);
787 LTTNG_ASSERT(payload);
788 LTTNG_ASSERT(nb_fd > 0);
789
790 lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd);
791
792 for (i = 0; i < nb_fd; i++) {
793 if (lttng_dynamic_array_add_element(&raw_fds, &default_value)) {
794 ret = -LTTNG_ERR_NOMEM;
795 goto end;
796 }
797 }
798
799 if (blocking) {
800 ret = lttcomm_recv_fds_unix_sock(sock, (int *) raw_fds.buffer.data, nb_fd);
801 } else {
802 ret = lttcomm_recv_fds_unix_sock_non_block(
803 sock, (int *) raw_fds.buffer.data, nb_fd);
804 }
805
806 if (ret <= 0) {
807 goto end;
808 }
809
810 add_ret = add_fds_to_payload(&raw_fds, payload);
811 if (add_ret != LTTNG_OK) {
812 ret = -(int) add_ret;
813 goto end;
814 }
815
816 end:
817 lttng_dynamic_array_reset(&raw_fds);
818 return ret;
819 }
820
821 ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, struct lttng_payload *payload)
822 {
823 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true);
824 }
825
826 ssize_t
827 lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd, struct lttng_payload *payload)
828 {
829 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false);
830 }
831
832 /*
833 * Recv a message accompanied by fd(s) from a non-blocking unix socket.
834 * Only use with non-blocking sockets.
835 *
836 * Returns the size of received data, or negative error value.
837 *
838 * Expect at most "nb_fd" file descriptors.
839 *
840 * Note that based on our comprehension, partial reception of fds is not
841 * possible since the FDs are actually in the control message. It is all or
842 * nothing, still the sender side can send the wrong number of fds.
843 */
844 ssize_t lttcomm_recv_fds_unix_sock_non_block(int sock, int *fds, size_t nb_fd)
845 {
846 struct iovec iov[1];
847 ssize_t ret = 0;
848 struct cmsghdr *cmsg;
849 size_t sizeof_fds = nb_fd * sizeof(int);
850
851 LTTNG_ASSERT(sock);
852 LTTNG_ASSERT(fds);
853 LTTNG_ASSERT(nb_fd > 0);
854
855 #ifdef __linux__
856 /* Account for the struct ucred cmsg in the buffer size */
857 #define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds) + CMSG_SPACE(sizeof(struct ucred))
858 #else
859 #define LTTNG_SOCK_RECV_FDS_BUF_SIZE CMSG_SPACE(sizeof_fds)
860 #endif /* __linux__ */
861
862 char recv_buf[LTTNG_SOCK_RECV_FDS_BUF_SIZE];
863 struct msghdr msg;
864 char dummy;
865
866 memset(&msg, 0, sizeof(msg));
867
868 /* Prepare to receive the structures */
869 iov[0].iov_base = &dummy;
870 iov[0].iov_len = 1;
871 msg.msg_iov = iov;
872 msg.msg_iovlen = 1;
873
874 cmsg = (struct cmsghdr *) recv_buf;
875 cmsg->cmsg_len = CMSG_LEN(sizeof_fds);
876 cmsg->cmsg_level = SOL_SOCKET;
877 cmsg->cmsg_type = SCM_RIGHTS;
878
879 msg.msg_control = cmsg;
880 msg.msg_controllen = CMSG_LEN(sizeof(recv_buf));
881 msg.msg_flags = 0;
882
883 retry:
884 ret = lttng_recvmsg_nosigpipe(sock, &msg);
885 if (ret < 0) {
886 if (errno == EINTR) {
887 goto retry;
888 } else {
889 /*
890 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
891 */
892 DIAGNOSTIC_PUSH
893 DIAGNOSTIC_IGNORE_LOGICAL_OP
894 if (errno == EAGAIN || errno == EWOULDBLOCK) {
895 DIAGNOSTIC_POP
896 /*
897 * This can happen in non blocking mode.
898 * Nothing was recv.
899 */
900 ret = 0;
901 goto end;
902 }
903
904 if (errno == EPIPE) {
905 /* Expected error, pass error to caller */
906 DBG3("EPIPE on recvmsg");
907 ret = -1;
908 goto end;
909 }
910
911 /* Unexpected error */
912 PERROR("recvmsg");
913 ret = -1;
914 goto end;
915 }
916 }
917
918 if (ret != 1) {
919 fprintf(stderr, "Error: Received %zd bytes, expected %d\n", ret, 1);
920 goto end;
921 }
922
923 if (msg.msg_flags & MSG_CTRUNC) {
924 fprintf(stderr, "Error: Control message truncated.\n");
925 ret = -1;
926 goto end;
927 }
928
929 /*
930 * If the socket was configured with SO_PASSCRED, the kernel will add a
931 * control message (cmsg) to the ancillary data of the unix socket. We
932 * need to expect a cmsg of the SCM_CREDENTIALS as the first control
933 * message.
934 */
935 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
936 if (cmsg->cmsg_level != SOL_SOCKET) {
937 fprintf(stderr, "Error: The socket needs to be of type SOL_SOCKET\n");
938 ret = -1;
939 goto end;
940 }
941 if (cmsg->cmsg_type == SCM_RIGHTS) {
942 /*
943 * We found the controle message for file descriptors,
944 * now copy the fds to the fds ptr and return success.
945 */
946 if (cmsg->cmsg_len != CMSG_LEN(sizeof_fds)) {
947 fprintf(stderr,
948 "Error: Received %zu bytes of"
949 "ancillary data for FDs, expected %zu\n",
950 (size_t) cmsg->cmsg_len,
951 (size_t) CMSG_LEN(sizeof_fds));
952 ret = -1;
953 goto end;
954 }
955 memcpy(fds, CMSG_DATA(cmsg), sizeof_fds);
956 ret = sizeof_fds;
957 goto end;
958 }
959 #ifdef __linux__
960 if (cmsg->cmsg_type == SCM_CREDENTIALS) {
961 /*
962 * Expect credentials to be sent when expecting fds even
963 * if no credential were include in the send(). The
964 * kernel adds them...
965 */
966 ret = -1;
967 }
968 #endif /* __linux__ */
969 }
970 end:
971 return ret;
972 }
973
974 /*
975 * Send a message with credentials over a unix socket.
976 *
977 * Returns the size of data sent, or negative error value.
978 */
979 ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len)
980 {
981 struct msghdr msg;
982 struct iovec iov[1];
983 ssize_t ret = -1;
984 #if defined(__linux__) || defined(__CYGWIN__)
985 struct cmsghdr *cmptr;
986 size_t sizeof_cred = sizeof(lttng_sock_cred);
987 char anc_buf[CMSG_SPACE(sizeof_cred)];
988 lttng_sock_cred *creds;
989
990 memset(anc_buf, 0, CMSG_SPACE(sizeof_cred) * sizeof(char));
991 #endif /* __linux__, __CYGWIN__ */
992
993 memset(&msg, 0, sizeof(msg));
994
995 LTTNG_ASSERT(sock);
996 LTTNG_ASSERT(buf);
997 LTTNG_ASSERT(len > 0);
998
999 iov[0].iov_base = (void *) buf;
1000 iov[0].iov_len = len;
1001 msg.msg_iov = iov;
1002 msg.msg_iovlen = 1;
1003
1004 #if defined(__linux__) || defined(__CYGWIN__)
1005 msg.msg_control = (caddr_t) anc_buf;
1006 msg.msg_controllen = CMSG_LEN(sizeof_cred);
1007
1008 cmptr = CMSG_FIRSTHDR(&msg);
1009 if (!cmptr) {
1010 return -1;
1011 }
1012 cmptr->cmsg_level = SOL_SOCKET;
1013 cmptr->cmsg_type = LTTNG_SOCK_CREDS;
1014 cmptr->cmsg_len = CMSG_LEN(sizeof_cred);
1015
1016 creds = (lttng_sock_cred *) CMSG_DATA(cmptr);
1017
1018 LTTNG_SOCK_SET_UID_CRED(creds, geteuid());
1019 LTTNG_SOCK_SET_GID_CRED(creds, getegid());
1020 LTTNG_SOCK_SET_PID_CRED(creds, getpid());
1021 #endif /* __linux__, __CYGWIN__ */
1022
1023 do {
1024 ret = sendmsg(sock, &msg, 0);
1025 } while (ret < 0 && errno == EINTR);
1026 if (ret < 0) {
1027 /*
1028 * Only warn about EPIPE when quiet mode is deactivated.
1029 * We consider EPIPE as expected.
1030 */
1031 if (errno != EPIPE || !lttng_opt_quiet) {
1032 PERROR("sendmsg");
1033 }
1034 }
1035 return ret;
1036 }
1037
1038 /*
1039 * Recv a message accompanied with credentials from a unix socket.
1040 *
1041 * Returns the size of received data, or negative error value.
1042 */
1043 ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, lttng_sock_cred *creds)
1044 {
1045 struct msghdr msg;
1046 struct iovec iov[1];
1047 ssize_t ret;
1048 size_t len_last;
1049 #if defined(__linux__) || defined(__CYGWIN__)
1050 struct cmsghdr *cmptr;
1051 size_t sizeof_cred = sizeof(lttng_sock_cred);
1052 char anc_buf[CMSG_SPACE(sizeof_cred)];
1053 #endif /* __linux__, __CYGWIN__ */
1054
1055 LTTNG_ASSERT(sock);
1056 LTTNG_ASSERT(buf);
1057 LTTNG_ASSERT(len > 0);
1058 LTTNG_ASSERT(creds);
1059
1060 memset(&msg, 0, sizeof(msg));
1061
1062 /* Prepare to receive the structures */
1063 iov[0].iov_base = buf;
1064 iov[0].iov_len = len;
1065 msg.msg_iov = iov;
1066 msg.msg_iovlen = 1;
1067
1068 #if defined(__linux__) || defined(__CYGWIN__)
1069 msg.msg_control = anc_buf;
1070 msg.msg_controllen = sizeof(anc_buf);
1071 #endif /* __linux__, __CYGWIN__ */
1072
1073 do {
1074 len_last = iov[0].iov_len;
1075 ret = recvmsg(sock, &msg, 0);
1076 if (ret > 0) {
1077 iov[0].iov_base = (char *) iov[0].iov_base + ret;
1078 iov[0].iov_len -= ret;
1079 LTTNG_ASSERT(ret <= len_last);
1080 }
1081 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
1082 if (ret < 0) {
1083 PERROR("recvmsg fds");
1084 goto end;
1085 } else if (ret > 0) {
1086 ret = len;
1087 }
1088 /* Else ret = 0 meaning an orderly shutdown. */
1089
1090 #if defined(__linux__) || defined(__CYGWIN__)
1091 if (msg.msg_flags & MSG_CTRUNC) {
1092 fprintf(stderr, "Error: Control message truncated.\n");
1093 ret = -1;
1094 goto end;
1095 }
1096
1097 cmptr = CMSG_FIRSTHDR(&msg);
1098 if (cmptr == nullptr) {
1099 fprintf(stderr, "Error: Invalid control message header\n");
1100 ret = -1;
1101 goto end;
1102 }
1103
1104 if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != LTTNG_SOCK_CREDS) {
1105 fprintf(stderr, "Didn't received any credentials\n");
1106 ret = -1;
1107 goto end;
1108 }
1109
1110 if (cmptr->cmsg_len != CMSG_LEN(sizeof_cred)) {
1111 fprintf(stderr,
1112 "Error: Received %zu bytes of ancillary data, expected %zu\n",
1113 (size_t) cmptr->cmsg_len,
1114 (size_t) CMSG_LEN(sizeof_cred));
1115 ret = -1;
1116 goto end;
1117 }
1118
1119 memcpy(creds, CMSG_DATA(cmptr), sizeof_cred);
1120 #elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
1121 if (lttng_get_unix_socket_peer_creds(sock, creds)) {
1122 fprintf(stderr, "ARG\n");
1123 ret = -1;
1124 goto end;
1125 }
1126 #else
1127 #error "Please implement credential support for your OS."
1128 #endif /* __linux__, __CYGWIN__ */
1129
1130 end:
1131 return ret;
1132 }
1133
1134 /*
1135 * Set socket option to use credentials passing.
1136 */
1137 #if defined(__linux__) || defined(__CYGWIN__)
1138 int lttcomm_setsockopt_creds_unix_sock(int sock)
1139 {
1140 int ret, on = 1;
1141
1142 /* Set socket for credentials retrieval */
1143 ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1144 if (ret < 0) {
1145 PERROR("setsockopt creds unix sock");
1146 }
1147 return ret;
1148 }
1149 #elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
1150 int lttcomm_setsockopt_creds_unix_sock(int sock __attribute__((unused)))
1151 {
1152 return 0;
1153 }
1154 #else
1155 #error "Please implement credential support for your OS."
1156 #endif /* __linux__ */
This page took 0.057076 seconds and 5 git commands to generate.