docs: Add supported versions and fix-backport policy
[lttng-tools.git] / src / common / unix.cpp
CommitLineData
0d37f2bc 1/*
21cf9b6b 2 * Copyright (C) 2011 EfficiOS Inc.
ab5be9fa 3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
0d37f2bc 4 *
c922647d 5 * SPDX-License-Identifier: LGPL-2.1-only
0d37f2bc 6 *
0d37f2bc
DG
7 */
8
6c1c0768 9#define _LGPL_SOURCE
28ab034a
JG
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
0d37f2bc
DG
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>
0d37f2bc 24
0d37f2bc
DG
25/*
26 * Connect to unix socket using the path name.
27 */
28int lttcomm_connect_unix_sock(const char *pathname)
29{
665886a6 30 struct sockaddr_un s_un;
0d37f2bc
DG
31 int fd, ret, closeret;
32
7f8bf467
JG
33 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
34 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
28ab034a
JG
35 pathname,
36 strlen(pathname) + 1,
37 sizeof(s_un.sun_path));
7f8bf467
JG
38 ret = -ENAMETOOLONG;
39 goto error;
40 }
41
0d37f2bc
DG
42 fd = socket(PF_UNIX, SOCK_STREAM, 0);
43 if (fd < 0) {
44 PERROR("socket");
45 ret = fd;
46 goto error;
47 }
48
665886a6
MJ
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';
0d37f2bc 53
665886a6 54 ret = connect(fd, (struct sockaddr *) &s_un, sizeof(s_un));
0d37f2bc
DG
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
65error_connect:
66 closeret = close(fd);
67 if (closeret) {
68 PERROR("close");
69 }
70error:
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 */
78int lttcomm_accept_unix_sock(int sock)
79{
80 int new_fd;
665886a6 81 struct sockaddr_un s_un;
50786a72 82 socklen_t len = sizeof(s_un);
0d37f2bc
DG
83
84 /* Blocking call */
665886a6 85 new_fd = accept(sock, (struct sockaddr *) &s_un, &len);
0d37f2bc
DG
86 if (new_fd < 0) {
87 PERROR("accept");
88 }
89
90 return new_fd;
91}
92
7567352f
MD
93int 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
0d37f2bc
DG
102/*
103 * Creates a AF_UNIX local socket using pathname bind the socket upon creation
104 * and return the fd.
105 */
106int lttcomm_create_unix_sock(const char *pathname)
107{
665886a6 108 struct sockaddr_un s_un;
7f8bf467 109 int fd = -1;
0d37f2bc
DG
110 int ret = -1;
111
7f8bf467
JG
112 if (strlen(pathname) >= sizeof(s_un.sun_path)) {
113 ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
28ab034a
JG
114 pathname,
115 strlen(pathname) + 1,
116 sizeof(s_un.sun_path));
7f8bf467
JG
117 ret = -ENAMETOOLONG;
118 goto error;
119 }
120
0d37f2bc
DG
121 /* Create server socket */
122 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
123 PERROR("socket");
124 goto error;
125 }
126
665886a6
MJ
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';
0d37f2bc
DG
131
132 /* Unlink the old file if present */
133 (void) unlink(pathname);
665886a6 134 ret = bind(fd, (struct sockaddr *) &s_un, sizeof(s_un));
0d37f2bc
DG
135 if (ret < 0) {
136 PERROR("bind");
137 goto error;
138 }
139
140 return fd;
141
142error:
17e75273
DG
143 if (fd >= 0) {
144 if (close(fd) < 0) {
145 PERROR("close create unix sock");
146 }
147 }
0d37f2bc
DG
148 return ret;
149}
150
151/*
152 * Make the socket listen using LTTNG_SESSIOND_COMM_MAX_LISTEN.
153 */
154int 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 */
172ssize_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;
7c5aef62 177 size_t len_last;
0d37f2bc 178
a0377dfe
FD
179 LTTNG_ASSERT(sock);
180 LTTNG_ASSERT(buf);
181 LTTNG_ASSERT(len > 0);
982583bd 182
0d37f2bc
DG
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 {
7c5aef62 191 len_last = iov[0].iov_len;
fbb1fd3a 192 ret = lttng_recvmsg_nosigpipe(sock, &msg);
7c5aef62 193 if (ret > 0) {
a6bc4ca9 194 iov[0].iov_base = (char *) iov[0].iov_base + ret;
7c5aef62 195 iov[0].iov_len -= ret;
a0377dfe 196 LTTNG_ASSERT(ret <= len_last);
7c5aef62
DG
197 }
198 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
0d37f2bc
DG
199 if (ret < 0) {
200 PERROR("recvmsg");
7c5aef62
DG
201 } else if (ret > 0) {
202 ret = len;
0d37f2bc 203 }
7c5aef62 204 /* Else ret = 0 meaning an orderly shutdown. */
0d37f2bc
DG
205
206 return ret;
207}
208
c72435ad
JG
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 *
44c180ca
JR
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 *
c72435ad
JG
216 * Return the size of received data.
217 */
c72435ad
JG
218ssize_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
a0377dfe
FD
224 LTTNG_ASSERT(sock);
225 LTTNG_ASSERT(buf);
226 LTTNG_ASSERT(len > 0);
982583bd 227
c72435ad
JG
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
235retry:
236 ret = lttng_recvmsg_nosigpipe(sock, &msg);
237 if (ret < 0) {
238 if (errno == EINTR) {
239 goto retry;
240 } else {
44c180ca
JR
241 /*
242 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
243 */
942003e5
MJ
244 DIAGNOSTIC_PUSH
245 DIAGNOSTIC_IGNORE_LOGICAL_OP
28ab034a
JG
246 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EPIPE) {
247 DIAGNOSTIC_POP
44c180ca
JR
248 /*
249 * Nothing was recv.
250 */
251 ret = 0;
252 goto end;
c72435ad 253 }
44c180ca
JR
254
255 /* Unexpected error */
256 PERROR("recvmsg");
257 ret = -1;
c72435ad
JG
258 goto end;
259 }
260 }
5b86bd5e 261
c72435ad
JG
262end:
263 return ret;
264}
265
0d37f2bc
DG
266/*
267 * Send buf data of size len. Using sendmsg API.
268 *
269 * Return the size of sent data.
270 */
c2d69327 271ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len)
0d37f2bc
DG
272{
273 struct msghdr msg;
274 struct iovec iov[1];
c72435ad 275 ssize_t ret;
0d37f2bc 276
a0377dfe
FD
277 LTTNG_ASSERT(sock);
278 LTTNG_ASSERT(buf);
279 LTTNG_ASSERT(len > 0);
982583bd 280
0d37f2bc
DG
281 memset(&msg, 0, sizeof(msg));
282
c2d69327 283 iov[0].iov_base = (void *) buf;
0d37f2bc
DG
284 iov[0].iov_len = len;
285 msg.msg_iov = iov;
286 msg.msg_iovlen = 1;
287
c72435ad
JG
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;
a6bc4ca9 306 iov[0].iov_base = (char *) iov[0].iov_base + ret;
c72435ad
JG
307 }
308 ret = len;
309end:
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 *
44c180ca
JR
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 *
c72435ad
JG
322 * Return the size of sent data.
323 */
c72435ad
JG
324ssize_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
a0377dfe
FD
330 LTTNG_ASSERT(sock);
331 LTTNG_ASSERT(buf);
332 LTTNG_ASSERT(len > 0);
982583bd 333
c72435ad
JG
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
341retry:
0d37f2bc
DG
342 ret = sendmsg(sock, &msg, 0);
343 if (ret < 0) {
c72435ad
JG
344 if (errno == EINTR) {
345 goto retry;
346 } else {
44c180ca
JR
347 /*
348 * We consider EPIPE and EAGAIN/EWOULDBLOCK as expected.
349 */
942003e5
MJ
350 DIAGNOSTIC_PUSH
351 DIAGNOSTIC_IGNORE_LOGICAL_OP
28ab034a
JG
352 if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EPIPE) {
353 DIAGNOSTIC_POP
44c180ca
JR
354 /*
355 * This can happen in non blocking mode.
356 * Nothing was sent.
357 */
358 ret = 0;
359 goto end;
c72435ad 360 }
44c180ca
JR
361
362 /* Unexpected error */
363 PERROR("sendmsg");
364 ret = -1;
c72435ad 365 goto end;
0d37f2bc
DG
366 }
367 }
c72435ad 368end:
0d37f2bc
DG
369 return ret;
370}
371
372/*
373 * Shutdown cleanly a unix socket.
374 */
375int 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) {
7d1f4920
MJ
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 }
0d37f2bc
DG
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 */
ac2f30af 407ssize_t lttcomm_send_fds_unix_sock(int sock, const int *fds, size_t nb_fd)
0d37f2bc
DG
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
a0377dfe
FD
417 LTTNG_ASSERT(sock);
418 LTTNG_ASSERT(fds);
419 LTTNG_ASSERT(nb_fd > 0);
982583bd 420
0d37f2bc 421 memset(&msg, 0, sizeof(msg));
b3f35e02 422 memset(tmp, 0, sizeof(tmp));
0d37f2bc
DG
423
424 if (nb_fd > LTTCOMM_MAX_SEND_FDS)
425 return -EINVAL;
426
28ab034a 427 msg.msg_control = (caddr_t) tmp;
0d37f2bc
DG
428 msg.msg_controllen = CMSG_LEN(sizeof_fds);
429
430 cmptr = CMSG_FIRSTHDR(&msg);
1d8d0328
MJ
431 if (!cmptr) {
432 return -1;
433 }
b3f35e02 434
0d37f2bc
DG
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
fe489250
JG
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 */
28ab034a
JG
467static ssize_t
468_lttcomm_send_payload_view_fds_unix_sock(int sock, struct lttng_payload_view *view, bool blocking)
fe489250
JG
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
cd9adb8b 475 lttng_dynamic_array_init(&raw_fds, sizeof(int), nullptr);
fe489250 476
3545ccee
JR
477 if (fd_count < 0) {
478 ret = -LTTNG_ERR_INVALID;
479 goto end;
480 }
481
fe489250
JG
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++) {
28ab034a 492 struct fd_handle *handle = lttng_payload_view_pop_fd_handle(view);
fe489250 493 const int raw_fd = fd_handle_get_fd(handle);
28ab034a 494 const int add_ret = lttng_dynamic_array_add_element(&raw_fds, &raw_fd);
fe489250
JG
495
496 fd_handle_put(handle);
497 if (add_ret) {
498 ret = -LTTNG_ERR_NOMEM;
499 goto end;
500 }
501 }
502
503 if (blocking) {
28ab034a 504 ret = lttcomm_send_fds_unix_sock(sock, (const int *) raw_fds.buffer.data, fd_count);
fe489250 505 } else {
28ab034a
JG
506 ret = lttcomm_send_fds_unix_sock_non_block(
507 sock, (const int *) raw_fds.buffer.data, fd_count);
fe489250
JG
508 }
509
510end:
511 lttng_dynamic_array_reset(&raw_fds);
512 return ret;
513}
514
28ab034a 515ssize_t lttcomm_send_payload_view_fds_unix_sock(int sock, struct lttng_payload_view *view)
fe489250
JG
516{
517 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, true);
518}
519
28ab034a 520ssize_t lttcomm_send_payload_view_fds_unix_sock_non_block(int sock, struct lttng_payload_view *view)
fe489250
JG
521{
522 return _lttcomm_send_payload_view_fds_unix_sock(sock, view, false);
523}
524
b72ce630
JR
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 */
b72ce630
JR
531ssize_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
a0377dfe
FD
541 LTTNG_ASSERT(sock);
542 LTTNG_ASSERT(fds);
543 LTTNG_ASSERT(nb_fd > 0);
982583bd 544
b72ce630
JR
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
28ab034a 551 msg.msg_control = (caddr_t) tmp;
b72ce630
JR
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
571retry:
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 */
942003e5
MJ
580 DIAGNOSTIC_PUSH
581 DIAGNOSTIC_IGNORE_LOGICAL_OP
b72ce630 582 if (errno == EAGAIN || errno == EWOULDBLOCK) {
28ab034a 583 DIAGNOSTIC_POP
b72ce630
JR
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
606end:
607 return ret;
608}
609
0d37f2bc
DG
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 */
618ssize_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);
b3f35e02 624
ba49ae8c
MJ
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];
0d37f2bc
DG
633 struct msghdr msg;
634 char dummy;
635
a0377dfe
FD
636 LTTNG_ASSERT(sock);
637 LTTNG_ASSERT(fds);
638 LTTNG_ASSERT(nb_fd > 0);
982583bd 639
0d37f2bc
DG
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;
b3f35e02
FD
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;
0d37f2bc 656
b72ce630
JR
657retry:
658 ret = lttng_recvmsg_nosigpipe(sock, &msg);
0d37f2bc 659 if (ret < 0) {
b72ce630
JR
660 if (errno == EINTR) {
661 goto retry;
662 } else {
663 /* We consider EPIPE and EAGAIN as expected. */
28ab034a 664 if (!lttng_opt_quiet && (errno != EPIPE && errno != EAGAIN)) {
b72ce630
JR
665 PERROR("recvmsg");
666 }
667 goto end;
668 }
669 }
670
671 if (ret != 1) {
28ab034a 672 fprintf(stderr, "Error: Received %zd bytes, expected %d\n", ret, 1);
0d37f2bc
DG
673 goto end;
674 }
b3f35e02 675
b72ce630
JR
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 */
cd9adb8b 688 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
b72ce630
JR
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)) {
28ab034a
JG
700 fprintf(stderr,
701 "Error: Received %zu bytes of"
b72ce630
JR
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 }
723end:
724 return ret;
725}
726
28ab034a 727static void close_raw_fd(void *ptr)
fe489250
JG
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
28ab034a
JG
740static enum lttng_error_code add_fds_to_payload(struct lttng_dynamic_array *raw_fds,
741 struct lttng_payload *payload)
fe489250
JG
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;
28ab034a 750 int *raw_fd = (int *) lttng_dynamic_array_get_element(raw_fds, i);
fe489250 751
a0377dfe 752 LTTNG_ASSERT(*raw_fd != -1);
5dbd9742 753
fe489250
JG
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
771end:
772 return ret_code;
773}
774
28ab034a
JG
775static ssize_t _lttcomm_recv_payload_fds_unix_sock(int sock,
776 size_t nb_fd,
777 struct lttng_payload *payload,
778 bool blocking)
fe489250 779{
5dbd9742 780 int i = 0;
fe489250
JG
781 enum lttng_error_code add_ret;
782 ssize_t ret;
5dbd9742 783 int default_value = -1;
fe489250
JG
784 struct lttng_dynamic_array raw_fds;
785
a0377dfe
FD
786 LTTNG_ASSERT(sock);
787 LTTNG_ASSERT(payload);
788 LTTNG_ASSERT(nb_fd > 0);
982583bd 789
fe489250 790 lttng_dynamic_array_init(&raw_fds, sizeof(int), close_raw_fd);
5dbd9742
JR
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 }
fe489250
JG
797 }
798
799 if (blocking) {
28ab034a 800 ret = lttcomm_recv_fds_unix_sock(sock, (int *) raw_fds.buffer.data, nb_fd);
fe489250
JG
801 } else {
802 ret = lttcomm_recv_fds_unix_sock_non_block(
28ab034a 803 sock, (int *) raw_fds.buffer.data, nb_fd);
fe489250
JG
804 }
805
b3ba184e 806 if (ret <= 0) {
fe489250
JG
807 goto end;
808 }
809
810 add_ret = add_fds_to_payload(&raw_fds, payload);
811 if (add_ret != LTTNG_OK) {
28ab034a 812 ret = -(int) add_ret;
fe489250
JG
813 goto end;
814 }
815
816end:
817 lttng_dynamic_array_reset(&raw_fds);
818 return ret;
819}
820
28ab034a 821ssize_t lttcomm_recv_payload_fds_unix_sock(int sock, size_t nb_fd, struct lttng_payload *payload)
fe489250
JG
822{
823 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, true);
824}
825
28ab034a
JG
826ssize_t
827lttcomm_recv_payload_fds_unix_sock_non_block(int sock, size_t nb_fd, struct lttng_payload *payload)
fe489250
JG
828{
829 return _lttcomm_recv_payload_fds_unix_sock(sock, nb_fd, payload, false);
830}
831
b72ce630
JR
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 */
b72ce630
JR
844ssize_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
a0377dfe
FD
851 LTTNG_ASSERT(sock);
852 LTTNG_ASSERT(fds);
853 LTTNG_ASSERT(nb_fd > 0);
982583bd 854
b72ce630
JR
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
883retry:
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 */
942003e5
MJ
892 DIAGNOSTIC_PUSH
893 DIAGNOSTIC_IGNORE_LOGICAL_OP
b72ce630 894 if (errno == EAGAIN || errno == EWOULDBLOCK) {
28ab034a 895 DIAGNOSTIC_POP
b72ce630
JR
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
0d37f2bc 918 if (ret != 1) {
28ab034a 919 fprintf(stderr, "Error: Received %zd bytes, expected %d\n", ret, 1);
0d37f2bc
DG
920 goto end;
921 }
b3f35e02 922
0d37f2bc
DG
923 if (msg.msg_flags & MSG_CTRUNC) {
924 fprintf(stderr, "Error: Control message truncated.\n");
925 ret = -1;
926 goto end;
927 }
b3f35e02
FD
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 */
cd9adb8b 935 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
b3f35e02
FD
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)) {
28ab034a
JG
947 fprintf(stderr,
948 "Error: Received %zu bytes of"
b3f35e02
FD
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 }
ba49ae8c 959#ifdef __linux__
b3f35e02
FD
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 */
b3f35e02
FD
966 ret = -1;
967 }
ba49ae8c 968#endif /* __linux__ */
0d37f2bc 969 }
0d37f2bc
DG
970end:
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 */
e368fb43 979ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len)
0d37f2bc
DG
980{
981 struct msghdr msg;
982 struct iovec iov[1];
983 ssize_t ret = -1;
9bc1a4b4 984#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
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;
8bbffd54
MJ
989
990 memset(anc_buf, 0, CMSG_SPACE(sizeof_cred) * sizeof(char));
9bc1a4b4 991#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
992
993 memset(&msg, 0, sizeof(msg));
994
a0377dfe
FD
995 LTTNG_ASSERT(sock);
996 LTTNG_ASSERT(buf);
997 LTTNG_ASSERT(len > 0);
982583bd 998
e368fb43 999 iov[0].iov_base = (void *) buf;
0d37f2bc
DG
1000 iov[0].iov_len = len;
1001 msg.msg_iov = iov;
1002 msg.msg_iovlen = 1;
1003
9bc1a4b4 1004#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1005 msg.msg_control = (caddr_t) anc_buf;
1006 msg.msg_controllen = CMSG_LEN(sizeof_cred);
1007
1008 cmptr = CMSG_FIRSTHDR(&msg);
1d8d0328
MJ
1009 if (!cmptr) {
1010 return -1;
1011 }
0d37f2bc
DG
1012 cmptr->cmsg_level = SOL_SOCKET;
1013 cmptr->cmsg_type = LTTNG_SOCK_CREDS;
1014 cmptr->cmsg_len = CMSG_LEN(sizeof_cred);
1015
28ab034a 1016 creds = (lttng_sock_cred *) CMSG_DATA(cmptr);
0d37f2bc
DG
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());
9bc1a4b4 1021#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
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 */
28ab034a 1043ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len, lttng_sock_cred *creds)
0d37f2bc
DG
1044{
1045 struct msghdr msg;
1046 struct iovec iov[1];
1047 ssize_t ret;
4100e49a 1048 size_t len_last;
9bc1a4b4 1049#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1050 struct cmsghdr *cmptr;
1051 size_t sizeof_cred = sizeof(lttng_sock_cred);
1052 char anc_buf[CMSG_SPACE(sizeof_cred)];
28ab034a 1053#endif /* __linux__, __CYGWIN__ */
0d37f2bc 1054
a0377dfe
FD
1055 LTTNG_ASSERT(sock);
1056 LTTNG_ASSERT(buf);
1057 LTTNG_ASSERT(len > 0);
1058 LTTNG_ASSERT(creds);
0d37f2bc 1059
982583bd 1060 memset(&msg, 0, sizeof(msg));
0d37f2bc
DG
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
9bc1a4b4 1068#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1069 msg.msg_control = anc_buf;
1070 msg.msg_controllen = sizeof(anc_buf);
9bc1a4b4 1071#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
1072
1073 do {
4100e49a 1074 len_last = iov[0].iov_len;
0d37f2bc 1075 ret = recvmsg(sock, &msg, 0);
4100e49a 1076 if (ret > 0) {
a6bc4ca9 1077 iov[0].iov_base = (char *) iov[0].iov_base + ret;
4100e49a 1078 iov[0].iov_len -= ret;
a0377dfe 1079 LTTNG_ASSERT(ret <= len_last);
4100e49a
DG
1080 }
1081 } while ((ret > 0 && ret < len_last) || (ret < 0 && errno == EINTR));
0d37f2bc
DG
1082 if (ret < 0) {
1083 PERROR("recvmsg fds");
1084 goto end;
4100e49a
DG
1085 } else if (ret > 0) {
1086 ret = len;
0d37f2bc 1087 }
4100e49a 1088 /* Else ret = 0 meaning an orderly shutdown. */
0d37f2bc 1089
9bc1a4b4 1090#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
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);
cd9adb8b 1098 if (cmptr == nullptr) {
0d37f2bc
DG
1099 fprintf(stderr, "Error: Invalid control message header\n");
1100 ret = -1;
1101 goto end;
1102 }
1103
28ab034a 1104 if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != LTTNG_SOCK_CREDS) {
0d37f2bc
DG
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)) {
28ab034a
JG
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));
0d37f2bc
DG
1115 ret = -1;
1116 goto end;
1117 }
1118
1119 memcpy(creds, CMSG_DATA(cmptr), sizeof_cred);
9bc1a4b4
JG
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;
0d37f2bc
DG
1125 }
1126#else
1127#error "Please implement credential support for your OS."
28ab034a 1128#endif /* __linux__, __CYGWIN__ */
0d37f2bc
DG
1129
1130end:
1131 return ret;
1132}
1133
1134/*
1135 * Set socket option to use credentials passing.
1136 */
9bc1a4b4 1137#if defined(__linux__) || defined(__CYGWIN__)
0d37f2bc
DG
1138int 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}
9bc1a4b4 1149#elif (defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__))
4eac90eb 1150int lttcomm_setsockopt_creds_unix_sock(int sock __attribute__((unused)))
0d37f2bc
DG
1151{
1152 return 0;
1153}
1154#else
1155#error "Please implement credential support for your OS."
1156#endif /* __linux__ */
This page took 0.139178 seconds and 4 git commands to generate.