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