D-Bus 1.15.4
dbus-sysdeps-unix.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27#include <config.h>
28
29#include "dbus-internals.h"
30#include "dbus-sysdeps.h"
31#include "dbus-sysdeps-unix.h"
32#include "dbus-threads.h"
33#include "dbus-protocol.h"
34#include "dbus-file.h"
35#include "dbus-transport.h"
36#include "dbus-string.h"
37#include "dbus-userdb.h"
38#include "dbus-list.h"
39#include "dbus-credentials.h"
40#include "dbus-nonce.h"
41
42#include <limits.h>
43#include <sys/types.h>
44#include <stdlib.h>
45#include <string.h>
46#include <signal.h>
47#include <unistd.h>
48#include <stdio.h>
49#include <fcntl.h>
50#include <sys/socket.h>
51#include <dirent.h>
52#include <sys/un.h>
53#include <pwd.h>
54#include <time.h>
55#include <locale.h>
56#include <sys/time.h>
57#include <sys/stat.h>
58#include <sys/wait.h>
59#include <netinet/in.h>
60#include <netinet/tcp.h>
61#include <netdb.h>
62#include <grp.h>
63#include <arpa/inet.h>
64
65#ifdef HAVE_ERRNO_H
66#include <errno.h>
67#endif
68#ifdef HAVE_LINUX_CLOSE_RANGE_H
69#include <linux/close_range.h>
70#endif
71#ifdef HAVE_SYSLOG_H
72#include <syslog.h>
73#endif
74#ifdef HAVE_WRITEV
75#include <sys/uio.h>
76#endif
77#ifdef HAVE_BACKTRACE
78#include <execinfo.h>
79#endif
80#ifdef HAVE_GETPEERUCRED
81#include <ucred.h>
82#endif
83#ifdef HAVE_ALLOCA_H
84#include <alloca.h>
85#endif
86#ifdef HAVE_SYS_RANDOM_H
87#include <sys/random.h>
88#endif
89#ifdef HAVE_SYS_SYSCALL_H
90#include <sys/syscall.h>
91#endif
92
93#ifdef HAVE_ADT
94#include <bsm/adt.h>
95#endif
96
97#ifdef HAVE_SYSTEMD
98#include <systemd/sd-daemon.h>
99#endif
100
101#if !DBUS_USE_SYNC
102#include <pthread.h>
103#endif
104
105#ifndef O_BINARY
106#define O_BINARY 0
107#endif
108
109#ifndef AI_ADDRCONFIG
110#define AI_ADDRCONFIG 0
111#endif
112
113#ifndef HAVE_SOCKLEN_T
114#define socklen_t int
115#endif
116
117#if defined (__sun) || defined (__sun__)
118/*
119 * CMS_SPACE etc. definitions for Solaris < 10, based on
120 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
121 * via
122 * http://wiki.opencsw.org/porting-faq#toc10
123 *
124 * These are only redefined for Solaris, for now: if your OS needs these too,
125 * please file a bug. (Or preferably, improve your OS so they're not needed.)
126 */
127
128# ifndef CMSG_ALIGN
129# ifdef __sun__
130# define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
131# else
132 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
133# define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
134 ~(sizeof (long) - 1))
135# endif
136# endif
137
138# ifndef CMSG_SPACE
139# define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
140 CMSG_ALIGN (len))
141# endif
142
143# ifndef CMSG_LEN
144# define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
145# endif
146
147#endif /* Solaris */
148
149#if defined(__linux__) && defined(__NR_close_range) && !defined(HAVE_CLOSE_RANGE)
150/* The kernel headers are new enough to have the close_range syscall,
151 * but glibc isn't new enough to have the syscall wrapper, so call the
152 * syscall directly. */
153static inline int
154close_range (unsigned int first,
155 unsigned int last,
156 unsigned int flags)
157{
158 return syscall (__NR_close_range, first, last, flags);
159}
160/* Now we can call that inline wrapper as though it was provided by glibc. */
161#define HAVE_CLOSE_RANGE
162#endif
163
179_dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
180 const char **error_str_p)
181{
182 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
183 DBUS_FORCE_STDOUT_NULL,
184 DBUS_FORCE_STDERR_NULL };
185 /* Should always get replaced with the real error before use */
186 const char *error_str = "Failed mysteriously";
187 int devnull = -1;
188 int saved_errno;
189 /* This function relies on the standard fds having their POSIX values. */
190 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
191 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
192 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
193 int i;
194
195 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
196 {
197 /* Because we rely on being single-threaded, and we want the
198 * standard fds to not be close-on-exec, we don't set it
199 * close-on-exec. */
200 if (devnull < i)
201 devnull = open ("/dev/null", O_RDWR);
202
203 if (devnull < 0)
204 {
205 error_str = "Failed to open /dev/null";
206 goto out;
207 }
208
209 /* We already opened all fds < i, so the only way this assertion
210 * could fail is if another thread closed one, and we document
211 * this function as not safe for multi-threading. */
212 _dbus_assert (devnull >= i);
213
214 if (devnull != i && (flags & relevant_flag[i]) != 0)
215 {
216 if (dup2 (devnull, i) < 0)
217 {
218 error_str = "Failed to dup2 /dev/null onto a standard fd";
219 goto out;
220 }
221 }
222 }
223
224 error_str = NULL;
225
226out:
227 saved_errno = errno;
228
229 if (devnull > STDERR_FILENO)
230 close (devnull);
231
232 if (error_str_p != NULL)
233 *error_str_p = error_str;
234
235 errno = saved_errno;
236 return (error_str == NULL);
237}
238
239static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
240 DBusError *error);
241
242static dbus_bool_t
243_dbus_open_socket (int *fd_p,
244 int domain,
245 int type,
246 int protocol,
247 DBusError *error)
248{
249#ifdef SOCK_CLOEXEC
250 dbus_bool_t cloexec_done;
251
252 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
253 cloexec_done = *fd_p >= 0;
254
255 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
256 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
257#endif
258 {
259 *fd_p = socket (domain, type, protocol);
260 }
261
262 if (*fd_p >= 0)
263 {
264#ifdef SOCK_CLOEXEC
265 if (!cloexec_done)
266#endif
267 {
269 }
270
271 _dbus_verbose ("socket fd %d opened\n", *fd_p);
272 return TRUE;
273 }
274 else
275 {
276 dbus_set_error(error,
278 "Failed to open socket: %s",
279 _dbus_strerror (errno));
280 return FALSE;
281 }
282}
283
294static dbus_bool_t
295_dbus_open_unix_socket (int *fd,
296 DBusError *error)
297{
298 return _dbus_open_socket(fd, AF_UNIX, SOCK_STREAM, 0, error);
299}
300
315 DBusError *error)
316{
317 dbus_bool_t rv;
318
319 _dbus_assert (fd != NULL);
320 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
321
322 rv = _dbus_close (fd->fd, error);
323 _dbus_socket_invalidate (fd);
324
325 return rv;
326}
327
337int
339 DBusString *buffer,
340 int count)
341{
342 return _dbus_read (fd.fd, buffer, count);
343}
344
355int
357 const DBusString *buffer,
358 int start,
359 int len)
360{
361#if HAVE_DECL_MSG_NOSIGNAL
362 const char *data;
363 int bytes_written;
364
365 data = _dbus_string_get_const_data_len (buffer, start, len);
366
367 again:
368
369 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
370
371 if (bytes_written < 0 && errno == EINTR)
372 goto again;
373
374 return bytes_written;
375
376#else
377 return _dbus_write (fd.fd, buffer, start, len);
378#endif
379}
380
393int
395 DBusString *buffer,
396 int count,
397 int *fds,
398 unsigned int *n_fds) {
399#ifndef HAVE_UNIX_FD_PASSING
400 int r;
401
402 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
403 return r;
404
405 *n_fds = 0;
406 return r;
407
408#else
409 int bytes_read;
410 int start;
411 struct msghdr m;
412 struct iovec iov;
413
414 _dbus_assert (count >= 0);
416
417 start = _dbus_string_get_length (buffer);
418
419 if (!_dbus_string_lengthen (buffer, count))
420 {
421 errno = ENOMEM;
422 return -1;
423 }
424
425 _DBUS_ZERO(iov);
426 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
427 iov.iov_len = count;
428
429 _DBUS_ZERO(m);
430 m.msg_iov = &iov;
431 m.msg_iovlen = 1;
432
433 /* Hmm, we have no clue how long the control data will actually be
434 that is queued for us. The least we can do is assume that the
435 caller knows. Hence let's make space for the number of fds that
436 we shall read at max plus the cmsg header. */
437 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
438
439 /* It's probably safe to assume that systems with SCM_RIGHTS also
440 know alloca() */
441 m.msg_control = alloca(m.msg_controllen);
442 memset(m.msg_control, 0, m.msg_controllen);
443
444 /* Do not include the padding at the end when we tell the kernel
445 * how much we're willing to receive. This avoids getting
446 * the padding filled with additional fds that we weren't expecting,
447 * if a (potentially malicious) sender included them. (fd.o #83622) */
448 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
449
450 again:
451
452 bytes_read = recvmsg (fd.fd, &m, 0
453#ifdef MSG_CMSG_CLOEXEC
454 |MSG_CMSG_CLOEXEC
455#endif
456 );
457
458 if (bytes_read < 0)
459 {
460 if (errno == EINTR)
461 goto again;
462 else
463 {
464 /* put length back (note that this doesn't actually realloc anything) */
465 _dbus_string_set_length (buffer, start);
466 return -1;
467 }
468 }
469 else
470 {
471 struct cmsghdr *cm;
472 dbus_bool_t found = FALSE;
473
474 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
475 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
476 {
477 size_t i;
478 int *payload = (int *) (void *) CMSG_DATA (cm);
479 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
480 size_t payload_len_fds;
481 size_t fds_to_use;
482
483 /* Every unsigned int fits in a size_t without truncation, so
484 * casting (size_t) *n_fds is OK */
485 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
486
487 if ((m.msg_flags & MSG_CTRUNC) && CMSG_NXTHDR(&m, cm) == NULL &&
488 (char *) payload + payload_len_bytes >
489 (char *) m.msg_control + m.msg_controllen)
490 {
491 /* This is the last cmsg in a truncated message and using
492 * cmsg_len would apparently overrun the allocated buffer.
493 * Some operating systems (illumos and Solaris are known) do
494 * not adjust cmsg_len in the last cmsg when truncation occurs.
495 * Adjust the payload length here. The calculation for
496 * payload_len_fds below will discard any trailing bytes that
497 * belong to an incomplete file descriptor - the kernel will
498 * have already closed that (at least for illumos and Solaris)
499 */
500 payload_len_bytes = m.msg_controllen -
501 ((char *) payload - (char *) m.msg_control);
502 }
503
504 payload_len_fds = payload_len_bytes / sizeof (int);
505
506 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
507 {
508 /* The fds in the payload will fit in our buffer */
509 fds_to_use = payload_len_fds;
510 }
511 else
512 {
513 /* Too many fds in the payload. This shouldn't happen
514 * any more because we're setting m.msg_controllen to
515 * the exact number we can accept, but be safe and
516 * truncate. */
517 fds_to_use = (size_t) *n_fds;
518
519 /* Close the excess fds to avoid DoS: if they stayed open,
520 * someone could send us an extra fd per message
521 * and we'd eventually run out. */
522 for (i = fds_to_use; i < payload_len_fds; i++)
523 {
524 close (payload[i]);
525 }
526 }
527
528 memcpy (fds, payload, fds_to_use * sizeof (int));
529 found = TRUE;
530 /* This narrowing cast from size_t to unsigned int cannot
531 * overflow because we have chosen fds_to_use
532 * to be <= *n_fds */
533 *n_fds = (unsigned int) fds_to_use;
534
535 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
536 worked, hence we need to go through this list and set
537 CLOEXEC everywhere in any case */
538 for (i = 0; i < fds_to_use; i++)
540
541 break;
542 }
543
544 if (!found)
545 *n_fds = 0;
546
547 if (m.msg_flags & MSG_CTRUNC)
548 {
549 unsigned int i;
550
551 /* Hmm, apparently the control data was truncated. The bad
552 thing is that we might have completely lost a couple of fds
553 without chance to recover them. Hence let's treat this as a
554 serious error. */
555
556 /* We still need to close whatever fds we *did* receive,
557 * otherwise they'll never get closed. (CVE-2020-12049) */
558 for (i = 0; i < *n_fds; i++)
559 close (fds[i]);
560
561 *n_fds = 0;
562 errno = ENOSPC;
563 _dbus_string_set_length (buffer, start);
564 return -1;
565 }
566
567 /* put length back (doesn't actually realloc) */
568 _dbus_string_set_length (buffer, start + bytes_read);
569
570#if 0
571 if (bytes_read > 0)
572 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
573#endif
574
575 return bytes_read;
576 }
577#endif
578}
579
580int
581_dbus_write_socket_with_unix_fds(DBusSocket fd,
582 const DBusString *buffer,
583 int start,
584 int len,
585 const int *fds,
586 int n_fds) {
587
588#ifndef HAVE_UNIX_FD_PASSING
589
590 if (n_fds > 0) {
591 errno = ENOTSUP;
592 return -1;
593 }
594
595 return _dbus_write_socket(fd, buffer, start, len);
596#else
597 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
598#endif
599}
600
601int
602_dbus_write_socket_with_unix_fds_two(DBusSocket fd,
603 const DBusString *buffer1,
604 int start1,
605 int len1,
606 const DBusString *buffer2,
607 int start2,
608 int len2,
609 const int *fds,
610 int n_fds) {
611
612#ifndef HAVE_UNIX_FD_PASSING
613
614 if (n_fds > 0) {
615 errno = ENOTSUP;
616 return -1;
617 }
618
619 return _dbus_write_socket_two(fd,
620 buffer1, start1, len1,
621 buffer2, start2, len2);
622#else
623
624 struct msghdr m;
625 struct cmsghdr *cm;
626 struct iovec iov[2];
627 int bytes_written;
628
629 _dbus_assert (len1 >= 0);
630 _dbus_assert (len2 >= 0);
631 _dbus_assert (n_fds >= 0);
632
633 _DBUS_ZERO(iov);
634 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
635 iov[0].iov_len = len1;
636
637 if (buffer2)
638 {
639 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
640 iov[1].iov_len = len2;
641 }
642
643 _DBUS_ZERO(m);
644 m.msg_iov = iov;
645 m.msg_iovlen = buffer2 ? 2 : 1;
646
647 if (n_fds > 0)
648 {
649 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
650 m.msg_control = alloca(m.msg_controllen);
651 memset(m.msg_control, 0, m.msg_controllen);
652
653 cm = CMSG_FIRSTHDR(&m);
654 cm->cmsg_level = SOL_SOCKET;
655 cm->cmsg_type = SCM_RIGHTS;
656 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
657 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
658 }
659
660 again:
661
662 bytes_written = sendmsg (fd.fd, &m, 0
663#if HAVE_DECL_MSG_NOSIGNAL
664 |MSG_NOSIGNAL
665#endif
666 );
667
668 if (bytes_written < 0 && errno == EINTR)
669 goto again;
670
671#if 0
672 if (bytes_written > 0)
673 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
674#endif
675
676 return bytes_written;
677#endif
678}
679
693int
695 const DBusString *buffer1,
696 int start1,
697 int len1,
698 const DBusString *buffer2,
699 int start2,
700 int len2)
701{
702#if HAVE_DECL_MSG_NOSIGNAL
703 struct iovec vectors[2];
704 const char *data1;
705 const char *data2;
706 int bytes_written;
707 struct msghdr m;
708
709 _dbus_assert (buffer1 != NULL);
710 _dbus_assert (start1 >= 0);
711 _dbus_assert (start2 >= 0);
712 _dbus_assert (len1 >= 0);
713 _dbus_assert (len2 >= 0);
714
715 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
716
717 if (buffer2 != NULL)
718 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
719 else
720 {
721 data2 = NULL;
722 start2 = 0;
723 len2 = 0;
724 }
725
726 vectors[0].iov_base = (char*) data1;
727 vectors[0].iov_len = len1;
728 vectors[1].iov_base = (char*) data2;
729 vectors[1].iov_len = len2;
730
731 _DBUS_ZERO(m);
732 m.msg_iov = vectors;
733 m.msg_iovlen = data2 ? 2 : 1;
734
735 again:
736
737 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
738
739 if (bytes_written < 0 && errno == EINTR)
740 goto again;
741
742 return bytes_written;
743
744#else
745 return _dbus_write_two (fd.fd, buffer1, start1, len1,
746 buffer2, start2, len2);
747#endif
748}
749
766int
768 DBusString *buffer,
769 int count)
770{
771 int bytes_read;
772 int start;
773 char *data;
774
775 _dbus_assert (count >= 0);
776
777 start = _dbus_string_get_length (buffer);
778
779 if (!_dbus_string_lengthen (buffer, count))
780 {
781 errno = ENOMEM;
782 return -1;
783 }
784
785 data = _dbus_string_get_data_len (buffer, start, count);
786
787 again:
788
789 bytes_read = read (fd, data, count);
790
791 if (bytes_read < 0)
792 {
793 if (errno == EINTR)
794 goto again;
795 else
796 {
797 /* put length back (note that this doesn't actually realloc anything) */
798 _dbus_string_set_length (buffer, start);
799 return -1;
800 }
801 }
802 else
803 {
804 /* put length back (doesn't actually realloc) */
805 _dbus_string_set_length (buffer, start + bytes_read);
806
807#if 0
808 if (bytes_read > 0)
809 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
810#endif
811
812 return bytes_read;
813 }
814}
815
826int
828 const DBusString *buffer,
829 int start,
830 int len)
831{
832 const char *data;
833 int bytes_written;
834
835 data = _dbus_string_get_const_data_len (buffer, start, len);
836
837 again:
838
839 bytes_written = write (fd, data, len);
840
841 if (bytes_written < 0 && errno == EINTR)
842 goto again;
843
844#if 0
845 if (bytes_written > 0)
846 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
847#endif
848
849 return bytes_written;
850}
851
872int
874 const DBusString *buffer1,
875 int start1,
876 int len1,
877 const DBusString *buffer2,
878 int start2,
879 int len2)
880{
881 _dbus_assert (buffer1 != NULL);
882 _dbus_assert (start1 >= 0);
883 _dbus_assert (start2 >= 0);
884 _dbus_assert (len1 >= 0);
885 _dbus_assert (len2 >= 0);
886
887#ifdef HAVE_WRITEV
888 {
889 struct iovec vectors[2];
890 const char *data1;
891 const char *data2;
892 int bytes_written;
893
894 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
895
896 if (buffer2 != NULL)
897 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
898 else
899 {
900 data2 = NULL;
901 start2 = 0;
902 len2 = 0;
903 }
904
905 vectors[0].iov_base = (char*) data1;
906 vectors[0].iov_len = len1;
907 vectors[1].iov_base = (char*) data2;
908 vectors[1].iov_len = len2;
909
910 again:
911
912 bytes_written = writev (fd,
913 vectors,
914 data2 ? 2 : 1);
915
916 if (bytes_written < 0 && errno == EINTR)
917 goto again;
918
919 return bytes_written;
920 }
921#else /* HAVE_WRITEV */
922 {
923 int ret1, ret2;
924
925 ret1 = _dbus_write (fd, buffer1, start1, len1);
926 if (ret1 == len1 && buffer2 != NULL)
927 {
928 ret2 = _dbus_write (fd, buffer2, start2, len2);
929 if (ret2 < 0)
930 ret2 = 0; /* we can't report an error as the first write was OK */
931
932 return ret1 + ret2;
933 }
934 else
935 return ret1;
936 }
937#endif /* !HAVE_WRITEV */
938}
939
958 dbus_bool_t abstract,
959 DBusError *error)
960{
961 DBusSocket fd = DBUS_SOCKET_INIT;
962 size_t path_len;
963 struct sockaddr_un addr;
964 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
965
966 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
967
968 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
969 path, abstract);
970
971
972 if (!_dbus_open_unix_socket (&fd.fd, error))
973 {
974 _DBUS_ASSERT_ERROR_IS_SET(error);
975 return fd;
976 }
977 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
978
979 _DBUS_ZERO (addr);
980 addr.sun_family = AF_UNIX;
981 path_len = strlen (path);
982
983 if (abstract)
984 {
985#ifdef __linux__
986 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
987 path_len++; /* Account for the extra nul byte added to the start of sun_path */
988
989 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
990 {
992 "Abstract socket name too long\n");
994 return fd;
995 }
996
997 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
998 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
999#else /* !__linux__ */
1001 "Operating system does not support abstract socket namespace\n");
1002 _dbus_close_socket (&fd, NULL);
1003 return fd;
1004#endif /* !__linux__ */
1005 }
1006 else
1007 {
1008 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1009 {
1011 "Socket name too long\n");
1012 _dbus_close_socket (&fd, NULL);
1013 return fd;
1014 }
1015
1016 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1017 }
1018
1019 if (connect (fd.fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1020 {
1021 dbus_set_error (error,
1022 _dbus_error_from_errno (errno),
1023 "Failed to connect to socket %s: %s",
1024 path, _dbus_strerror (errno));
1025
1026 _dbus_close_socket (&fd, NULL);
1027 return fd;
1028 }
1029
1030 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1031 {
1032 _DBUS_ASSERT_ERROR_IS_SET (error);
1033
1034 _dbus_close_socket (&fd, NULL);
1035 return fd;
1036 }
1037
1038 return fd;
1039}
1040
1054_dbus_connect_exec (const char *path,
1055 char *const argv[],
1056 DBusError *error)
1057{
1058 DBusSocket s = DBUS_SOCKET_INIT;
1059 int fds[2];
1060 pid_t pid;
1061 int retval;
1062 dbus_bool_t cloexec_done = 0;
1063
1064 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1065
1066 _dbus_verbose ("connecting to process %s\n", path);
1067
1068#ifdef SOCK_CLOEXEC
1069 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1070 cloexec_done = (retval >= 0);
1071
1072 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1073#endif
1074 {
1075 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1076 }
1077
1078 if (retval < 0)
1079 {
1080 dbus_set_error (error,
1081 _dbus_error_from_errno (errno),
1082 "Failed to create socket pair: %s",
1083 _dbus_strerror (errno));
1084 _dbus_assert (!_dbus_socket_is_valid (s));
1085 return s;
1086 }
1087
1088 if (!cloexec_done)
1089 {
1092 }
1093
1094 /* Make sure our output buffers aren't redundantly printed by both the
1095 * parent and the child */
1096 fflush (stdout);
1097 fflush (stderr);
1098
1099 pid = fork ();
1100 if (pid < 0)
1101 {
1102 dbus_set_error (error,
1103 _dbus_error_from_errno (errno),
1104 "Failed to fork() to call %s: %s",
1105 path, _dbus_strerror (errno));
1106 close (fds[0]);
1107 close (fds[1]);
1108 _dbus_assert (!_dbus_socket_is_valid (s));
1109 return s;
1110 }
1111
1112 if (pid == 0)
1113 {
1114 /* child */
1115 close (fds[0]);
1116
1117 dup2 (fds[1], STDIN_FILENO);
1118 dup2 (fds[1], STDOUT_FILENO);
1119
1120 if (fds[1] != STDIN_FILENO &&
1121 fds[1] != STDOUT_FILENO)
1122 close (fds[1]);
1123
1124 /* Inherit STDERR and the controlling terminal from the
1125 parent */
1126
1127 _dbus_close_all ();
1128
1129 execvp (path, (char * const *) argv);
1130
1131 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1132
1133 _exit(1);
1134 }
1135
1136 /* parent */
1137 close (fds[1]);
1138
1139 if (!_dbus_set_fd_nonblocking (fds[0], error))
1140 {
1141 _DBUS_ASSERT_ERROR_IS_SET (error);
1142
1143 close (fds[0]);
1144 _dbus_assert (!_dbus_socket_is_valid (s));
1145 return s;
1146 }
1147
1148 s.fd = fds[0];
1149 return s;
1150}
1151
1171 dbus_bool_t abstract,
1172 DBusError *error)
1173{
1174 DBusSocket s = DBUS_SOCKET_INIT;
1175 int listen_fd;
1176 struct sockaddr_un addr;
1177 size_t path_len;
1178 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1179
1180 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1181
1182 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1183 path, abstract);
1184
1185 if (!_dbus_open_unix_socket (&listen_fd, error))
1186 {
1187 _DBUS_ASSERT_ERROR_IS_SET(error);
1188 return s;
1189 }
1190 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1191
1192 _DBUS_ZERO (addr);
1193 addr.sun_family = AF_UNIX;
1194 path_len = strlen (path);
1195
1196 if (abstract)
1197 {
1198#ifdef __linux__
1199 /* remember that abstract names aren't nul-terminated so we rely
1200 * on sun_path being filled in with zeroes above.
1201 */
1202 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1203 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1204
1205 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1206 {
1208 "Abstract socket name too long\n");
1209 _dbus_close (listen_fd, NULL);
1210 return s;
1211 }
1212
1213 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1214 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1215#else /* !__linux__ */
1217 "Operating system does not support abstract socket namespace\n");
1218 _dbus_close (listen_fd, NULL);
1219 return s;
1220#endif /* !__linux__ */
1221 }
1222 else
1223 {
1224 /* Discussed security implications of this with Nalin,
1225 * and we couldn't think of where it would kick our ass, but
1226 * it still seems a bit sucky. It also has non-security suckage;
1227 * really we'd prefer to exit if the socket is already in use.
1228 * But there doesn't seem to be a good way to do this.
1229 *
1230 * Just to be extra careful, I threw in the stat() - clearly
1231 * the stat() can't *fix* any security issue, but it at least
1232 * avoids inadvertent/accidental data loss.
1233 */
1234 {
1235 struct stat sb;
1236
1237 if (stat (path, &sb) == 0 &&
1238 S_ISSOCK (sb.st_mode))
1239 unlink (path);
1240 }
1241
1242 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1243 {
1245 "Socket name too long\n");
1246 _dbus_close (listen_fd, NULL);
1247 return s;
1248 }
1249
1250 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1251 }
1252
1253 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1254 {
1255 dbus_set_error (error, _dbus_error_from_errno (errno),
1256 "Failed to bind socket \"%s\": %s",
1257 path, _dbus_strerror (errno));
1258 _dbus_close (listen_fd, NULL);
1259 return s;
1260 }
1261
1262 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1263 {
1264 dbus_set_error (error, _dbus_error_from_errno (errno),
1265 "Failed to listen on socket \"%s\": %s",
1266 path, _dbus_strerror (errno));
1267 _dbus_close (listen_fd, NULL);
1268 return s;
1269 }
1270
1271 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1272 {
1273 _DBUS_ASSERT_ERROR_IS_SET (error);
1274 _dbus_close (listen_fd, NULL);
1275 return s;
1276 }
1277
1278 /* Try opening up the permissions, but if we can't, just go ahead
1279 * and continue, maybe it will be good enough.
1280 */
1281 if (!abstract && chmod (path, 0777) < 0)
1282 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1283
1284 s.fd = listen_fd;
1285 return s;
1286}
1287
1298int
1300 DBusError *error)
1301{
1302#ifdef HAVE_SYSTEMD
1303 int r, n;
1304 int fd;
1305 DBusSocket *new_fds;
1306
1307 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1308
1309 n = sd_listen_fds (TRUE);
1310 if (n < 0)
1311 {
1313 "Failed to acquire systemd socket: %s",
1314 _dbus_strerror (-n));
1315 return -1;
1316 }
1317
1318 if (n <= 0)
1319 {
1321 "No socket received.");
1322 return -1;
1323 }
1324
1325 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1326 {
1327 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1328 if (r < 0)
1329 {
1331 "Failed to verify systemd socket type: %s",
1332 _dbus_strerror (-r));
1333 return -1;
1334 }
1335
1336 if (!r)
1337 {
1339 "Passed socket has wrong type.");
1340 return -1;
1341 }
1342 }
1343
1344 /* OK, the file descriptors are all good, so let's take posession of
1345 them then. */
1346
1347 new_fds = dbus_new (DBusSocket, n);
1348 if (!new_fds)
1349 {
1351 "Failed to allocate file handle array.");
1352 goto fail;
1353 }
1354
1355 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1356 {
1357 if (!_dbus_set_fd_nonblocking (fd, error))
1358 {
1359 _DBUS_ASSERT_ERROR_IS_SET (error);
1360 goto fail;
1361 }
1362
1363 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1364 }
1365
1366 *fds = new_fds;
1367 return n;
1368
1369 fail:
1370
1371 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1372 {
1373 _dbus_close (fd, NULL);
1374 }
1375
1376 dbus_free (new_fds);
1377 return -1;
1378#else
1380 "dbus was compiled without systemd support");
1381 return -1;
1382#endif
1383}
1384
1385/* Convert an error code from getaddrinfo() or getnameinfo() into
1386 * a D-Bus error name. */
1387static const char *
1388_dbus_error_from_gai (int gai_res,
1389 int saved_errno)
1390{
1391 switch (gai_res)
1392 {
1393#ifdef EAI_FAMILY
1394 case EAI_FAMILY:
1395 /* ai_family not supported (at all) */
1397#endif
1398
1399#ifdef EAI_SOCKTYPE
1400 case EAI_SOCKTYPE:
1401 /* ai_socktype not supported (at all) */
1403#endif
1404
1405#ifdef EAI_MEMORY
1406 case EAI_MEMORY:
1407 /* Out of memory */
1408 return DBUS_ERROR_NO_MEMORY;
1409#endif
1410
1411#ifdef EAI_SYSTEM
1412 case EAI_SYSTEM:
1413 /* Unspecified system error, details in errno */
1414 return _dbus_error_from_errno (saved_errno);
1415#endif
1416
1417 case 0:
1418 /* It succeeded, but we didn't get any addresses? */
1419 return DBUS_ERROR_FAILED;
1420
1421 /* EAI_AGAIN: Transient failure */
1422 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1423 /* EAI_FAIL: Non-recoverable failure */
1424 /* EAI_NODATA: host exists but has no addresses */
1425 /* EAI_NONAME: host does not exist */
1426 /* EAI_OVERFLOW: argument buffer overflow */
1427 /* EAI_SERVICE: service not available for specified socket
1428 * type (we should never see this because we use numeric
1429 * ports) */
1430 default:
1431 return DBUS_ERROR_FAILED;
1432 }
1433}
1434
1450 const char *port,
1451 const char *family,
1452 DBusError *error)
1453{
1454 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1455}
1456
1458_dbus_connect_tcp_socket_with_nonce (const char *host,
1459 const char *port,
1460 const char *family,
1461 const char *noncefile,
1462 DBusError *error)
1463{
1464 int saved_errno = 0;
1465 DBusList *connect_errors = NULL;
1466 DBusSocket fd = DBUS_SOCKET_INIT;
1467 int res;
1468 struct addrinfo hints;
1469 struct addrinfo *ai = NULL;
1470 const struct addrinfo *tmp;
1471 DBusError *connect_error;
1472
1473 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1474
1475 _DBUS_ZERO (hints);
1476
1477 if (!family)
1478 hints.ai_family = AF_UNSPEC;
1479 else if (!strcmp(family, "ipv4"))
1480 hints.ai_family = AF_INET;
1481 else if (!strcmp(family, "ipv6"))
1482 hints.ai_family = AF_INET6;
1483 else
1484 {
1485 dbus_set_error (error,
1487 "Unknown address family %s", family);
1488 return _dbus_socket_get_invalid ();
1489 }
1490 hints.ai_protocol = IPPROTO_TCP;
1491 hints.ai_socktype = SOCK_STREAM;
1492 hints.ai_flags = AI_ADDRCONFIG;
1493
1494 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1495 {
1496 dbus_set_error (error,
1497 _dbus_error_from_gai (res, errno),
1498 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1499 host, port, gai_strerror(res), res);
1500 goto out;
1501 }
1502
1503 tmp = ai;
1504 while (tmp)
1505 {
1506 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1507 {
1508 _DBUS_ASSERT_ERROR_IS_SET(error);
1509 _dbus_socket_invalidate (&fd);
1510 goto out;
1511 }
1512 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1513
1514 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1515 {
1516 saved_errno = errno;
1517 _dbus_close_socket (&fd, NULL);
1518
1519 connect_error = dbus_new0 (DBusError, 1);
1520
1521 if (connect_error == NULL)
1522 {
1523 _DBUS_SET_OOM (error);
1524 goto out;
1525 }
1526
1527 dbus_error_init (connect_error);
1528 _dbus_set_error_with_inet_sockaddr (connect_error,
1529 tmp->ai_addr, tmp->ai_addrlen,
1530 "Failed to connect to socket",
1531 saved_errno);
1532
1533 if (!_dbus_list_append (&connect_errors, connect_error))
1534 {
1535 dbus_error_free (connect_error);
1536 dbus_free (connect_error);
1537 _DBUS_SET_OOM (error);
1538 goto out;
1539 }
1540
1541 tmp = tmp->ai_next;
1542 continue;
1543 }
1544
1545 break;
1546 }
1547
1548 if (!_dbus_socket_is_valid (fd))
1549 {
1550 _dbus_combine_tcp_errors (&connect_errors, "Failed to connect",
1551 host, port, error);
1552 goto out;
1553 }
1554
1555 if (noncefile != NULL)
1556 {
1557 DBusString noncefileStr;
1558 dbus_bool_t ret;
1559 _dbus_string_init_const (&noncefileStr, noncefile);
1560 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1561
1562 if (!ret)
1563 {
1564 _dbus_close_socket (&fd, NULL);
1565 goto out;
1566 }
1567 }
1568
1569 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1570 {
1571 _dbus_close_socket (&fd, NULL);
1572 goto out;
1573 }
1574
1575out:
1576 if (ai != NULL)
1577 freeaddrinfo (ai);
1578
1579 while ((connect_error = _dbus_list_pop_first (&connect_errors)))
1580 {
1581 dbus_error_free (connect_error);
1582 dbus_free (connect_error);
1583 }
1584
1585 return fd;
1586}
1587
1605int
1606_dbus_listen_tcp_socket (const char *host,
1607 const char *port,
1608 const char *family,
1609 DBusString *retport,
1610 const char **retfamily,
1611 DBusSocket **fds_p,
1612 DBusError *error)
1613{
1614 int saved_errno;
1615 int nlisten_fd = 0, res, i;
1616 DBusList *bind_errors = NULL;
1617 DBusError *bind_error = NULL;
1618 DBusSocket *listen_fd = NULL;
1619 struct addrinfo hints;
1620 struct addrinfo *ai, *tmp;
1621 unsigned int reuseaddr;
1622 dbus_bool_t have_ipv4 = FALSE;
1623 dbus_bool_t have_ipv6 = FALSE;
1624
1625 *fds_p = NULL;
1626 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1627
1628 _DBUS_ZERO (hints);
1629
1630 if (!family)
1631 hints.ai_family = AF_UNSPEC;
1632 else if (!strcmp(family, "ipv4"))
1633 hints.ai_family = AF_INET;
1634 else if (!strcmp(family, "ipv6"))
1635 hints.ai_family = AF_INET6;
1636 else
1637 {
1638 dbus_set_error (error,
1640 "Unknown address family %s", family);
1641 return -1;
1642 }
1643
1644 hints.ai_protocol = IPPROTO_TCP;
1645 hints.ai_socktype = SOCK_STREAM;
1646 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1647
1648 redo_lookup_with_port:
1649 ai = NULL;
1650 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1651 {
1652 dbus_set_error (error,
1653 _dbus_error_from_gai (res, errno),
1654 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1655 host ? host : "*", port, gai_strerror(res), res);
1656 goto failed;
1657 }
1658
1659 tmp = ai;
1660 while (tmp)
1661 {
1662 int fd = -1, tcp_nodelay_on;
1663 DBusSocket *newlisten_fd;
1664
1665 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1666 {
1667 _DBUS_ASSERT_ERROR_IS_SET(error);
1668 goto failed;
1669 }
1670 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1671
1672 reuseaddr = 1;
1673 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1674 {
1675 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1676 host ? host : "*", port, _dbus_strerror (errno));
1677 }
1678
1679 /* Nagle's algorithm imposes a huge delay on the initial messages
1680 going over TCP. */
1681 tcp_nodelay_on = 1;
1682 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1683 {
1684 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1685 host ? host : "*", port, _dbus_strerror (errno));
1686 }
1687
1688 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1689 {
1690 saved_errno = errno;
1691 _dbus_close(fd, NULL);
1692
1693 /*
1694 * We don't treat this as a fatal error, because there might be
1695 * other addresses that we can listen on. In particular:
1696 *
1697 * - If saved_errno is EADDRINUSE after we
1698 * "goto redo_lookup_with_port" after binding a port on one of the
1699 * possible addresses, we will try to bind that same port on
1700 * every address, including the same address again for a second
1701 * time, which will fail with EADDRINUSE.
1702 *
1703 * - If saved_errno is EADDRINUSE, it might be because binding to
1704 * an IPv6 address implicitly binds to a corresponding IPv4
1705 * address or vice versa (e.g. Linux with bindv6only=0).
1706 *
1707 * - If saved_errno is EADDRNOTAVAIL when we asked for family
1708 * AF_UNSPEC, it might be because IPv6 is disabled for this
1709 * particular interface (e.g. Linux with
1710 * /proc/sys/net/ipv6/conf/lo/disable_ipv6).
1711 */
1712 bind_error = dbus_new0 (DBusError, 1);
1713
1714 if (bind_error == NULL)
1715 {
1716 _DBUS_SET_OOM (error);
1717 goto failed;
1718 }
1719
1720 dbus_error_init (bind_error);
1721 _dbus_set_error_with_inet_sockaddr (bind_error, tmp->ai_addr, tmp->ai_addrlen,
1722 "Failed to bind socket",
1723 saved_errno);
1724
1725 if (!_dbus_list_append (&bind_errors, bind_error))
1726 {
1727 dbus_error_free (bind_error);
1728 dbus_free (bind_error);
1729 _DBUS_SET_OOM (error);
1730 goto failed;
1731 }
1732
1733 /* Try the next address, maybe it will work better */
1734 tmp = tmp->ai_next;
1735 continue;
1736 }
1737
1738 if (listen (fd, 30 /* backlog */) < 0)
1739 {
1740 saved_errno = errno;
1741 _dbus_close (fd, NULL);
1742 _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen,
1743 "Failed to listen on socket",
1744 saved_errno);
1745 goto failed;
1746 }
1747
1748 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1749 if (!newlisten_fd)
1750 {
1751 _dbus_close (fd, NULL);
1753 "Failed to allocate file handle array");
1754 goto failed;
1755 }
1756 listen_fd = newlisten_fd;
1757 listen_fd[nlisten_fd].fd = fd;
1758 nlisten_fd++;
1759
1760 if (tmp->ai_addr->sa_family == AF_INET)
1761 have_ipv4 = TRUE;
1762 else if (tmp->ai_addr->sa_family == AF_INET6)
1763 have_ipv6 = TRUE;
1764
1765 if (!_dbus_string_get_length(retport))
1766 {
1767 /* If the user didn't specify a port, or used 0, then
1768 the kernel chooses a port. After the first address
1769 is bound to, we need to force all remaining addresses
1770 to use the same port */
1771 if (!port || !strcmp(port, "0"))
1772 {
1773 int result;
1774 struct sockaddr_storage addr;
1775 socklen_t addrlen;
1776 char portbuf[50];
1777
1778 addrlen = sizeof(addr);
1779 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1780
1781 if (result == -1)
1782 {
1783 saved_errno = errno;
1784 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1785 "Failed to retrieve socket name for \"%s:%s\": %s",
1786 host ? host : "*", port, _dbus_strerror (saved_errno));
1787 goto failed;
1788 }
1789
1790 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1791 portbuf, sizeof(portbuf),
1792 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1793 {
1794 saved_errno = errno;
1795 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1796 "Failed to resolve port \"%s:%s\": %s (%d)",
1797 host ? host : "*", port, gai_strerror(res), res);
1798 goto failed;
1799 }
1800
1801 if (!_dbus_string_append(retport, portbuf))
1802 {
1804 goto failed;
1805 }
1806
1807 /* Release current address list & redo lookup */
1808 port = _dbus_string_get_const_data(retport);
1809 freeaddrinfo(ai);
1810 goto redo_lookup_with_port;
1811 }
1812 else
1813 {
1814 if (!_dbus_string_append(retport, port))
1815 {
1817 goto failed;
1818 }
1819 }
1820 }
1821
1822 tmp = tmp->ai_next;
1823 }
1824 freeaddrinfo(ai);
1825 ai = NULL;
1826
1827 if (!nlisten_fd)
1828 {
1829 _dbus_combine_tcp_errors (&bind_errors, "Failed to bind", host,
1830 port, error);
1831 goto failed;
1832 }
1833
1834 if (have_ipv4 && !have_ipv6)
1835 *retfamily = "ipv4";
1836 else if (!have_ipv4 && have_ipv6)
1837 *retfamily = "ipv6";
1838
1839 for (i = 0 ; i < nlisten_fd ; i++)
1840 {
1841 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1842 {
1843 goto failed;
1844 }
1845 }
1846
1847 *fds_p = listen_fd;
1848
1849 /* This list might be non-empty even on success, because we might be
1850 * ignoring EADDRINUSE or EADDRNOTAVAIL */
1851 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1852 {
1853 dbus_error_free (bind_error);
1854 dbus_free (bind_error);
1855 }
1856
1857 return nlisten_fd;
1858
1859 failed:
1860 if (ai)
1861 freeaddrinfo(ai);
1862 for (i = 0 ; i < nlisten_fd ; i++)
1863 _dbus_close(listen_fd[i].fd, NULL);
1864
1865 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1866 {
1867 dbus_error_free (bind_error);
1868 dbus_free (bind_error);
1869 }
1870
1871 dbus_free(listen_fd);
1872 return -1;
1873}
1874
1875static dbus_bool_t
1876write_credentials_byte (int server_fd,
1877 DBusError *error)
1878{
1879 int bytes_written;
1880 char buf[1] = { '\0' };
1881#if defined(HAVE_CMSGCRED)
1882 union {
1883 struct cmsghdr hdr;
1884 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1885 } cmsg;
1886 struct iovec iov;
1887 struct msghdr msg;
1888 iov.iov_base = buf;
1889 iov.iov_len = 1;
1890
1891 _DBUS_ZERO(msg);
1892 msg.msg_iov = &iov;
1893 msg.msg_iovlen = 1;
1894
1895 msg.msg_control = (caddr_t) &cmsg;
1896 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1897 _DBUS_ZERO(cmsg);
1898 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1899 cmsg.hdr.cmsg_level = SOL_SOCKET;
1900 cmsg.hdr.cmsg_type = SCM_CREDS;
1901#endif
1902
1903 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1904
1905 again:
1906
1907#if defined(HAVE_CMSGCRED)
1908 bytes_written = sendmsg (server_fd, &msg, 0
1909#if HAVE_DECL_MSG_NOSIGNAL
1910 |MSG_NOSIGNAL
1911#endif
1912 );
1913
1914 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1915 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1916 * only allows that on AF_UNIX. Try just doing a send() instead. */
1917 if (bytes_written < 0 && errno == EINVAL)
1918#endif
1919 {
1920 bytes_written = send (server_fd, buf, 1, 0
1921#if HAVE_DECL_MSG_NOSIGNAL
1922 |MSG_NOSIGNAL
1923#endif
1924 );
1925 }
1926
1927 if (bytes_written < 0 && errno == EINTR)
1928 goto again;
1929
1930 if (bytes_written < 0)
1931 {
1932 dbus_set_error (error, _dbus_error_from_errno (errno),
1933 "Failed to write credentials byte: %s",
1934 _dbus_strerror (errno));
1935 return FALSE;
1936 }
1937 else if (bytes_written == 0)
1938 {
1940 "wrote zero bytes writing credentials byte");
1941 return FALSE;
1942 }
1943 else
1944 {
1945 _dbus_assert (bytes_written == 1);
1946 _dbus_verbose ("wrote credentials byte\n");
1947 return TRUE;
1948 }
1949}
1950
1951/* return FALSE on OOM, TRUE otherwise, even if no groups were found */
1952static dbus_bool_t
1953add_groups_to_credentials (int client_fd,
1954 DBusCredentials *credentials,
1955 dbus_gid_t primary)
1956{
1957#if defined(__linux__) && defined(SO_PEERGROUPS)
1958 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1959 gid_t *buf = NULL;
1960 socklen_t len = 1024;
1961 dbus_bool_t oom = FALSE;
1962 /* libdbus has a different representation of group IDs just to annoy you */
1963 dbus_gid_t *converted_gids = NULL;
1964 dbus_bool_t need_primary = TRUE;
1965 size_t n_gids;
1966 size_t i;
1967
1968 n_gids = ((size_t) len) / sizeof (gid_t);
1969 buf = dbus_new (gid_t, n_gids);
1970
1971 if (buf == NULL)
1972 return FALSE;
1973
1974 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERGROUPS, buf, &len) < 0)
1975 {
1976 int e = errno;
1977 gid_t *replacement;
1978
1979 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1980 _dbus_strerror (e), (unsigned long) len);
1981
1982 if (e != ERANGE || (size_t) len <= n_gids * sizeof (gid_t))
1983 {
1984 _dbus_verbose ("Failed to getsockopt(SO_PEERGROUPS): %s\n",
1985 _dbus_strerror (e));
1986 goto out;
1987 }
1988
1989 /* If not enough space, len is updated to be enough.
1990 * Try again with a large enough buffer. */
1991 n_gids = ((size_t) len) / sizeof (gid_t);
1992 replacement = dbus_realloc (buf, len);
1993
1994 if (replacement == NULL)
1995 {
1996 oom = TRUE;
1997 goto out;
1998 }
1999
2000 buf = replacement;
2001 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
2002 }
2003
2004 if (len <= 0)
2005 {
2006 _dbus_verbose ("getsockopt(SO_PEERGROUPS) yielded <= 0 bytes: %ld\n",
2007 (long) len);
2008 goto out;
2009 }
2010
2011 if (len > n_gids * sizeof (gid_t))
2012 {
2013 _dbus_verbose ("%lu > %zu", (unsigned long) len, n_gids * sizeof (gid_t));
2014 _dbus_assert_not_reached ("getsockopt(SO_PEERGROUPS) overflowed");
2015 }
2016
2017 if (len % sizeof (gid_t) != 0)
2018 {
2019 _dbus_verbose ("getsockopt(SO_PEERGROUPS) did not return an "
2020 "integer multiple of sizeof(gid_t): %lu should be "
2021 "divisible by %zu",
2022 (unsigned long) len, sizeof (gid_t));
2023 goto out;
2024 }
2025
2026 /* Allocate an extra space for the primary group ID */
2027 n_gids = ((size_t) len) / sizeof (gid_t);
2028
2029 /* If n_gids is less than this, then (n_gids + 1) certainly doesn't
2030 * overflow, and neither does multiplying that by sizeof(dbus_gid_t).
2031 * This is using _DBUS_INT32_MAX as a conservative lower bound for
2032 * the maximum size_t. */
2033 if (n_gids >= (_DBUS_INT32_MAX / sizeof (dbus_gid_t)) - 1)
2034 {
2035 _dbus_verbose ("getsockopt(SO_PEERGROUPS) returned a huge number "
2036 "of groups (%lu bytes), ignoring",
2037 (unsigned long) len);
2038 goto out;
2039 }
2040
2041 converted_gids = dbus_new (dbus_gid_t, n_gids + 1);
2042
2043 if (converted_gids == NULL)
2044 {
2045 oom = TRUE;
2046 goto out;
2047 }
2048
2049 for (i = 0; i < n_gids; i++)
2050 {
2051 converted_gids[i] = (dbus_gid_t) buf[i];
2052
2053 if (converted_gids[i] == primary)
2054 need_primary = FALSE;
2055 }
2056
2057 if (need_primary && primary != DBUS_GID_UNSET)
2058 {
2059 converted_gids[n_gids] = primary;
2060 n_gids++;
2061 }
2062
2063 _dbus_credentials_take_unix_gids (credentials, converted_gids, n_gids);
2064
2065out:
2066 dbus_free (buf);
2067 return !oom;
2068#else
2069 /* no error */
2070 return TRUE;
2071#endif
2072}
2073
2074/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
2075static dbus_bool_t
2076add_linux_security_label_to_credentials (int client_fd,
2077 DBusCredentials *credentials)
2078{
2079#if defined(__linux__) && defined(SO_PEERSEC)
2080 DBusString buf;
2081 socklen_t len = 1024;
2082 dbus_bool_t oom = FALSE;
2083
2084 if (!_dbus_string_init_preallocated (&buf, len) ||
2085 !_dbus_string_set_length (&buf, len))
2086 return FALSE;
2087
2088 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
2089 _dbus_string_get_data (&buf), &len) < 0)
2090 {
2091 int e = errno;
2092
2093 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
2094 _dbus_strerror (e), (unsigned long) len);
2095
2096 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
2097 {
2098 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
2099 _dbus_strerror (e));
2100 goto out;
2101 }
2102
2103 /* If not enough space, len is updated to be enough.
2104 * Try again with a large enough buffer. */
2105 if (!_dbus_string_set_length (&buf, len))
2106 {
2107 oom = TRUE;
2108 goto out;
2109 }
2110
2111 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
2112 }
2113
2114 if (len <= 0)
2115 {
2116 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
2117 (unsigned long) len);
2118 goto out;
2119 }
2120
2121 if (len > _dbus_string_get_length_uint (&buf))
2122 {
2123 _dbus_verbose ("%lu > %u", (unsigned long) len,
2124 _dbus_string_get_length_uint (&buf));
2125 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
2126 }
2127
2128 if (_dbus_string_get_byte (&buf, len - 1) == 0)
2129 {
2130 /* the kernel included the trailing \0 in its count,
2131 * but DBusString always has an extra \0 after the data anyway */
2132 _dbus_verbose ("subtracting trailing \\0\n");
2133 len--;
2134 }
2135
2136 if (!_dbus_string_set_length (&buf, len))
2137 {
2138 _dbus_assert_not_reached ("shortening string should not lead to OOM");
2139 oom = TRUE;
2140 goto out;
2141 }
2142
2143 if (strlen (_dbus_string_get_const_data (&buf)) != len)
2144 {
2145 /* LSM people on the linux-security-module@ mailing list say this
2146 * should never happen: the label should be a bytestring with
2147 * an optional trailing \0 */
2148 _dbus_verbose ("security label from kernel had an embedded \\0, "
2149 "ignoring it\n");
2150 goto out;
2151 }
2152
2153 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
2154 (unsigned long) len,
2156
2159 {
2160 oom = TRUE;
2161 goto out;
2162 }
2163
2164out:
2165 _dbus_string_free (&buf);
2166 return !oom;
2167#else
2168 /* no error */
2169 return TRUE;
2170#endif
2171}
2172
2215 DBusCredentials *credentials,
2216 DBusError *error)
2217{
2218 struct msghdr msg;
2219 struct iovec iov;
2220 char buf;
2221 dbus_uid_t uid_read;
2222 dbus_gid_t primary_gid_read;
2223 dbus_pid_t pid_read;
2224 int bytes_read;
2225
2226#ifdef HAVE_CMSGCRED
2227 union {
2228 struct cmsghdr hdr;
2229 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
2230 } cmsg;
2231#endif
2232
2233 /* The POSIX spec certainly doesn't promise this, but
2234 * we need these assertions to fail as soon as we're wrong about
2235 * it so we can do the porting fixups
2236 */
2237 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2238 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2239 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2240
2241 uid_read = DBUS_UID_UNSET;
2242 primary_gid_read = DBUS_GID_UNSET;
2243 pid_read = DBUS_PID_UNSET;
2244
2245 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2246
2247 _dbus_credentials_clear (credentials);
2248
2249 iov.iov_base = &buf;
2250 iov.iov_len = 1;
2251
2252 _DBUS_ZERO(msg);
2253 msg.msg_iov = &iov;
2254 msg.msg_iovlen = 1;
2255
2256#if defined(HAVE_CMSGCRED)
2257 _DBUS_ZERO(cmsg);
2258 msg.msg_control = (caddr_t) &cmsg;
2259 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
2260#endif
2261
2262 again:
2263 bytes_read = recvmsg (client_fd.fd, &msg, 0);
2264
2265 if (bytes_read < 0)
2266 {
2267 if (errno == EINTR)
2268 goto again;
2269
2270 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2271 * normally only call read_credentials if the socket was ready
2272 * for reading
2273 */
2274
2275 dbus_set_error (error, _dbus_error_from_errno (errno),
2276 "Failed to read credentials byte: %s",
2277 _dbus_strerror (errno));
2278 return FALSE;
2279 }
2280 else if (bytes_read == 0)
2281 {
2282 /* this should not happen unless we are using recvmsg wrong,
2283 * so is essentially here for paranoia
2284 */
2286 "Failed to read credentials byte (zero-length read)");
2287 return FALSE;
2288 }
2289 else if (buf != '\0')
2290 {
2292 "Credentials byte was not nul");
2293 return FALSE;
2294 }
2295
2296 _dbus_verbose ("read credentials byte\n");
2297
2298 {
2299#ifdef SO_PEERCRED
2300 /* Supported by at least Linux and OpenBSD, with minor differences.
2301 *
2302 * This mechanism passes the process ID through and does not require
2303 * the peer's cooperation, so we prefer it over all others. Notably,
2304 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2305 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2306 * because this is much less fragile.
2307 */
2308#ifdef __OpenBSD__
2309 struct sockpeercred cr;
2310#else
2311 struct ucred cr;
2312#endif
2313 socklen_t cr_len = sizeof (cr);
2314
2315 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2316 {
2317 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2318 _dbus_strerror (errno));
2319 }
2320 else if (cr_len != sizeof (cr))
2321 {
2322 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2323 cr_len, (int) sizeof (cr));
2324 }
2325 else
2326 {
2327 pid_read = cr.pid;
2328 uid_read = cr.uid;
2329#ifdef __linux__
2330 /* Do other platforms have cr.gid? (Not that it really matters,
2331 * because the gid is useless to us unless we know the complete
2332 * group vector, which we only know on Linux.) */
2333 primary_gid_read = cr.gid;
2334#endif
2335 }
2336#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2337 /* Another variant of the above - used on NetBSD
2338 */
2339 struct unpcbid cr;
2340 socklen_t cr_len = sizeof (cr);
2341
2342 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2343 {
2344 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2345 _dbus_strerror (errno));
2346 }
2347 else if (cr_len != sizeof (cr))
2348 {
2349 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2350 cr_len, (int) sizeof (cr));
2351 }
2352 else
2353 {
2354 pid_read = cr.unp_pid;
2355 uid_read = cr.unp_euid;
2356 }
2357#elif defined(HAVE_CMSGCRED)
2358 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2359 * presence of that struct implies SCM_CREDS. Supported by at least
2360 * FreeBSD and DragonflyBSD.
2361 *
2362 * This mechanism requires the peer to help us (it has to send us a
2363 * SCM_CREDS message) but it does pass the process ID through,
2364 * which makes it better than getpeereid().
2365 */
2366 struct cmsgcred *cred;
2367 struct cmsghdr *cmsgp;
2368
2369 for (cmsgp = CMSG_FIRSTHDR (&msg);
2370 cmsgp != NULL;
2371 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2372 {
2373 if (cmsgp->cmsg_type == SCM_CREDS &&
2374 cmsgp->cmsg_level == SOL_SOCKET &&
2375 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2376 {
2377 cred = (struct cmsgcred *) (void *) CMSG_DATA (cmsgp);
2378 pid_read = cred->cmcred_pid;
2379 uid_read = cred->cmcred_euid;
2380 break;
2381 }
2382 }
2383
2384#elif defined(HAVE_GETPEERUCRED)
2385 /* Supported in at least Solaris >= 10. It should probably be higher
2386 * up this list, because it carries the pid and we use this code path
2387 * for audit data. */
2388 ucred_t * ucred = NULL;
2389 if (getpeerucred (client_fd.fd, &ucred) == 0)
2390 {
2391#ifdef HAVE_ADT
2392 adt_session_data_t *adth = NULL;
2393#endif
2394 pid_read = ucred_getpid (ucred);
2395 uid_read = ucred_geteuid (ucred);
2396#ifdef HAVE_ADT
2397 /* generate audit session data based on socket ucred */
2398 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2399 {
2400 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2401 }
2402 else
2403 {
2404 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2405 {
2406 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2407 }
2408 else
2409 {
2410 adt_export_data_t *data = NULL;
2411 size_t size = adt_export_session_data (adth, &data);
2412 if (size <= 0)
2413 {
2414 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2415 }
2416 else
2417 {
2418 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2419 free (data);
2420 }
2421 }
2422 (void) adt_end_session (adth);
2423 }
2424#endif /* HAVE_ADT */
2425 }
2426 else
2427 {
2428 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2429 }
2430 if (ucred != NULL)
2431 ucred_free (ucred);
2432
2433 /* ----------------------------------------------------------------
2434 * When adding new mechanisms, please add them above this point
2435 * if they support passing the process ID through, or below if not.
2436 * ---------------------------------------------------------------- */
2437
2438#elif defined(HAVE_GETPEEREID)
2439 /* getpeereid() originates from D.J. Bernstein and is fairly
2440 * widely-supported. According to a web search, it might be present in
2441 * any/all of:
2442 *
2443 * - AIX?
2444 * - Blackberry?
2445 * - Cygwin
2446 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2447 * - Mac OS X
2448 * - Minix 3.1.8+
2449 * - MirBSD?
2450 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2451 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2452 * - QNX?
2453 */
2454 uid_t euid;
2455 gid_t egid;
2456 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2457 {
2458 uid_read = euid;
2459 }
2460 else
2461 {
2462 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2463 }
2464#else /* no supported mechanism */
2465
2466#warning Socket credentials not supported on this Unix OS
2467#warning Please tell https://gitlab.freedesktop.org/dbus/dbus/-/issues/new
2468
2469 /* Please add other operating systems known to support at least one of
2470 * the mechanisms above to this list, keeping alphabetical order.
2471 * Everything not in this list is best-effort.
2472 */
2473#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2474 defined(__linux__) || \
2475 defined(__OpenBSD__) || \
2476 defined(__NetBSD__)
2477# error Credentials passing not working on this OS is a regression!
2478#endif
2479
2480 _dbus_verbose ("Socket credentials not supported on this OS\n");
2481#endif
2482 }
2483
2484 _dbus_verbose ("Credentials:"
2485 " pid "DBUS_PID_FORMAT
2486 " uid "DBUS_UID_FORMAT
2487 "\n",
2488 pid_read,
2489 uid_read);
2490
2491 if (pid_read != DBUS_PID_UNSET)
2492 {
2493 if (!_dbus_credentials_add_pid (credentials, pid_read))
2494 {
2495 _DBUS_SET_OOM (error);
2496 return FALSE;
2497 }
2498 }
2499
2500 if (uid_read != DBUS_UID_UNSET)
2501 {
2502 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2503 {
2504 _DBUS_SET_OOM (error);
2505 return FALSE;
2506 }
2507 }
2508
2509 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2510 {
2511 _DBUS_SET_OOM (error);
2512 return FALSE;
2513 }
2514
2515 /* We don't put any groups in the credentials unless we can put them
2516 * all there. */
2517 if (!add_groups_to_credentials (client_fd.fd, credentials, primary_gid_read))
2518 {
2519 _DBUS_SET_OOM (error);
2520 return FALSE;
2521 }
2522
2523 return TRUE;
2524}
2525
2545 DBusError *error)
2546{
2547 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2548
2549 if (write_credentials_byte (server_fd.fd, error))
2550 return TRUE;
2551 else
2552 return FALSE;
2553}
2554
2566{
2567 DBusSocket client_fd;
2568 struct sockaddr addr;
2569 socklen_t addrlen;
2570#ifdef HAVE_ACCEPT4
2571 dbus_bool_t cloexec_done;
2572#endif
2573
2574 addrlen = sizeof (addr);
2575
2576 retry:
2577
2578#ifdef HAVE_ACCEPT4
2579 /*
2580 * At compile-time, we assume that if accept4() is available in
2581 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2582 * not necessarily true that either is supported by the running kernel.
2583 */
2584 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2585 cloexec_done = client_fd.fd >= 0;
2586
2587 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2588#endif
2589 {
2590 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2591 }
2592
2593 if (client_fd.fd < 0)
2594 {
2595 if (errno == EINTR)
2596 goto retry;
2597 }
2598
2599 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2600
2601#ifdef HAVE_ACCEPT4
2602 if (!cloexec_done)
2603#endif
2604 {
2605 _dbus_fd_set_close_on_exec(client_fd.fd);
2606 }
2607
2608 return client_fd;
2609}
2610
2621{
2622 const char *directory;
2623 struct stat sb;
2624
2625 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2626
2627 directory = _dbus_string_get_const_data (dir);
2628
2629 if (stat (directory, &sb) < 0)
2630 {
2631 dbus_set_error (error, _dbus_error_from_errno (errno),
2632 "%s", _dbus_strerror (errno));
2633
2634 return FALSE;
2635 }
2636
2637 if (sb.st_uid != geteuid ())
2638 {
2640 "%s directory is owned by user %lu, not %lu",
2641 directory,
2642 (unsigned long) sb.st_uid,
2643 (unsigned long) geteuid ());
2644 return FALSE;
2645 }
2646
2647 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2648 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2649 {
2651 "%s directory is not private to the user", directory);
2652 return FALSE;
2653 }
2654
2655 return TRUE;
2656}
2657
2658static dbus_bool_t
2659fill_user_info_from_passwd (struct passwd *p,
2660 DBusUserInfo *info,
2661 DBusError *error)
2662{
2663 _dbus_assert (p->pw_name != NULL);
2664 _dbus_assert (p->pw_dir != NULL);
2665
2666 info->uid = p->pw_uid;
2667 info->primary_gid = p->pw_gid;
2668 info->username = _dbus_strdup (p->pw_name);
2669 info->homedir = _dbus_strdup (p->pw_dir);
2670
2671 if (info->username == NULL ||
2672 info->homedir == NULL)
2673 {
2675 return FALSE;
2676 }
2677
2678 return TRUE;
2679}
2680
2681static dbus_bool_t
2682fill_user_info (DBusUserInfo *info,
2683 dbus_uid_t uid,
2684 const DBusString *username,
2685 DBusError *error)
2686{
2687 const char *username_c;
2688
2689 /* exactly one of username/uid provided */
2690 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2691 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2692
2693 info->uid = DBUS_UID_UNSET;
2695 info->group_ids = NULL;
2696 info->n_group_ids = 0;
2697 info->username = NULL;
2698 info->homedir = NULL;
2699
2700 if (username != NULL)
2701 username_c = _dbus_string_get_const_data (username);
2702 else
2703 username_c = NULL;
2704
2705 /* For now assuming that the getpwnam() and getpwuid() flavors
2706 * are always symmetrical, if not we have to add more configure
2707 * checks
2708 */
2709
2710#ifdef HAVE_GETPWNAM_R
2711 {
2712 struct passwd *p;
2713 int result;
2714 size_t buflen;
2715 char *buf;
2716 struct passwd p_str;
2717
2718 /* retrieve maximum needed size for buf */
2719 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2720
2721 /* sysconf actually returns a long, but everything else expects size_t,
2722 * so just recast here.
2723 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2724 */
2725 if ((long) buflen <= 0)
2726 buflen = 1024;
2727
2728 result = -1;
2729 while (1)
2730 {
2731 buf = dbus_malloc (buflen);
2732 if (buf == NULL)
2733 {
2735 return FALSE;
2736 }
2737
2738 p = NULL;
2739 if (uid != DBUS_UID_UNSET)
2740 result = getpwuid_r (uid, &p_str, buf, buflen,
2741 &p);
2742 else
2743 result = getpwnam_r (username_c, &p_str, buf, buflen,
2744 &p);
2745 //Try a bigger buffer if ERANGE was returned
2746 if (result == ERANGE && buflen < 512 * 1024)
2747 {
2748 dbus_free (buf);
2749 buflen *= 2;
2750 }
2751 else
2752 {
2753 break;
2754 }
2755 }
2756 if (result == 0 && p == &p_str)
2757 {
2758 if (!fill_user_info_from_passwd (p, info, error))
2759 {
2760 dbus_free (buf);
2761 return FALSE;
2762 }
2763 dbus_free (buf);
2764 }
2765 else
2766 {
2767 dbus_set_error (error, _dbus_error_from_errno (errno),
2768 "User \"%s\" unknown or no memory to allocate password entry\n",
2769 username_c ? username_c : "???");
2770 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2771 dbus_free (buf);
2772 return FALSE;
2773 }
2774 }
2775#else /* ! HAVE_GETPWNAM_R */
2776 {
2777 /* I guess we're screwed on thread safety here */
2778 struct passwd *p;
2779
2780#warning getpwnam_r() not available, please report this to the dbus maintainers with details of your OS
2781
2782 if (uid != DBUS_UID_UNSET)
2783 p = getpwuid (uid);
2784 else
2785 p = getpwnam (username_c);
2786
2787 if (p != NULL)
2788 {
2789 if (!fill_user_info_from_passwd (p, info, error))
2790 {
2791 return FALSE;
2792 }
2793 }
2794 else
2795 {
2796 dbus_set_error (error, _dbus_error_from_errno (errno),
2797 "User \"%s\" unknown or no memory to allocate password entry\n",
2798 username_c ? username_c : "???");
2799 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2800 return FALSE;
2801 }
2802 }
2803#endif /* ! HAVE_GETPWNAM_R */
2804
2805 /* Fill this in so we can use it to get groups */
2806 username_c = info->username;
2807
2808#ifdef HAVE_GETGROUPLIST
2809 {
2810 gid_t *buf;
2811 int buf_count;
2812 int i;
2813 int initial_buf_count;
2814
2815 initial_buf_count = 17;
2816 buf_count = initial_buf_count;
2817 buf = dbus_new (gid_t, buf_count);
2818 if (buf == NULL)
2819 {
2821 goto failed;
2822 }
2823
2824 if (getgrouplist (username_c,
2825 info->primary_gid,
2826 buf, &buf_count) < 0)
2827 {
2828 gid_t *new;
2829 /* Presumed cause of negative return code: buf has insufficient
2830 entries to hold the entire group list. The Linux behavior in this
2831 case is to pass back the actual number of groups in buf_count, but
2832 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2833 So as a hack, try to help out a bit by guessing a larger
2834 number of groups, within reason.. might still fail, of course,
2835 but we can at least print a more informative message. I looked up
2836 the "right way" to do this by downloading Apple's own source code
2837 for the "id" command, and it turns out that they use an
2838 undocumented library function getgrouplist_2 (!) which is not
2839 declared in any header in /usr/include (!!). That did not seem
2840 like the way to go here.
2841 */
2842 if (buf_count == initial_buf_count)
2843 {
2844 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2845 }
2846 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2847 if (new == NULL)
2848 {
2850 dbus_free (buf);
2851 goto failed;
2852 }
2853
2854 buf = new;
2855
2856 errno = 0;
2857 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2858 {
2859 if (errno == 0)
2860 {
2861 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2862 username_c, buf_count, buf_count);
2863 }
2864 else
2865 {
2866 dbus_set_error (error,
2867 _dbus_error_from_errno (errno),
2868 "Failed to get groups for username \"%s\" primary GID "
2869 DBUS_GID_FORMAT ": %s\n",
2870 username_c, info->primary_gid,
2871 _dbus_strerror (errno));
2872 dbus_free (buf);
2873 goto failed;
2874 }
2875 }
2876 }
2877
2878 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2879 if (info->group_ids == NULL)
2880 {
2882 dbus_free (buf);
2883 goto failed;
2884 }
2885
2886 for (i = 0; i < buf_count; ++i)
2887 info->group_ids[i] = buf[i];
2888
2889 info->n_group_ids = buf_count;
2890
2891 dbus_free (buf);
2892 }
2893#else /* HAVE_GETGROUPLIST */
2894 {
2895 /* We just get the one group ID */
2896 info->group_ids = dbus_new (dbus_gid_t, 1);
2897 if (info->group_ids == NULL)
2898 {
2900 goto failed;
2901 }
2902
2903 info->n_group_ids = 1;
2904
2905 (info->group_ids)[0] = info->primary_gid;
2906 }
2907#endif /* HAVE_GETGROUPLIST */
2908
2909 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2910
2911 return TRUE;
2912
2913 failed:
2914 _DBUS_ASSERT_ERROR_IS_SET (error);
2915 return FALSE;
2916}
2917
2928 const DBusString *username,
2929 DBusError *error)
2930{
2931 return fill_user_info (info, DBUS_UID_UNSET,
2932 username, error);
2933}
2934
2945 dbus_uid_t uid,
2946 DBusError *error)
2947{
2948 return fill_user_info (info, uid,
2949 NULL, error);
2950}
2951
2967{
2968 /* The POSIX spec certainly doesn't promise this, but
2969 * we need these assertions to fail as soon as we're wrong about
2970 * it so we can do the porting fixups
2971 */
2972 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2973 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2974 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2975
2976 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2977 return FALSE;
2978 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2979 return FALSE;
2980
2981 return TRUE;
2982}
2983
2997{
2998 return _dbus_string_append_uint (str,
2999 _dbus_geteuid ());
3000}
3001
3008{
3009 return getpid ();
3010}
3011
3017{
3018 return getuid ();
3019}
3020
3026{
3027 return geteuid ();
3028}
3029
3036unsigned long
3038{
3039 return getpid ();
3040}
3041
3042#if !DBUS_USE_SYNC
3043/* To be thread-safe by default on platforms that don't necessarily have
3044 * atomic operations (notably Debian armel, which is armv4t), we must
3045 * use a mutex that can be initialized statically, like this.
3046 * GLib >= 2.32 uses a similar system.
3047 */
3048static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
3049#endif
3050
3059{
3060#if DBUS_USE_SYNC
3061 return __sync_add_and_fetch(&atomic->value, 1)-1;
3062#else
3063 dbus_int32_t res;
3064
3065 pthread_mutex_lock (&atomic_mutex);
3066 res = atomic->value;
3067 atomic->value += 1;
3068 pthread_mutex_unlock (&atomic_mutex);
3069
3070 return res;
3071#endif
3072}
3073
3082{
3083#if DBUS_USE_SYNC
3084 return __sync_sub_and_fetch(&atomic->value, 1)+1;
3085#else
3086 dbus_int32_t res;
3087
3088 pthread_mutex_lock (&atomic_mutex);
3089 res = atomic->value;
3090 atomic->value -= 1;
3091 pthread_mutex_unlock (&atomic_mutex);
3092
3093 return res;
3094#endif
3095}
3096
3106{
3107#if DBUS_USE_SYNC
3108 __sync_synchronize ();
3109 return atomic->value;
3110#else
3111 dbus_int32_t res;
3112
3113 pthread_mutex_lock (&atomic_mutex);
3114 res = atomic->value;
3115 pthread_mutex_unlock (&atomic_mutex);
3116
3117 return res;
3118#endif
3119}
3120
3126void
3128{
3129#if DBUS_USE_SYNC
3130 /* Atomic version of "*atomic &= 0; return *atomic" */
3131 __sync_and_and_fetch (&atomic->value, 0);
3132#else
3133 pthread_mutex_lock (&atomic_mutex);
3134 atomic->value = 0;
3135 pthread_mutex_unlock (&atomic_mutex);
3136#endif
3137}
3138
3144void
3146{
3147#if DBUS_USE_SYNC
3148 /* Atomic version of "*atomic |= 1; return *atomic" */
3149 __sync_or_and_fetch (&atomic->value, 1);
3150#else
3151 pthread_mutex_lock (&atomic_mutex);
3152 atomic->value = 1;
3153 pthread_mutex_unlock (&atomic_mutex);
3154#endif
3155}
3156
3165int
3167 int n_fds,
3168 int timeout_milliseconds)
3169{
3170#if defined(HAVE_POLL) && !defined(BROKEN_POLL)
3171 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
3172 if (timeout_milliseconds < -1)
3173 {
3174 timeout_milliseconds = -1;
3175 }
3176
3177 return poll (fds,
3178 n_fds,
3179 timeout_milliseconds);
3180#else /* ! HAVE_POLL */
3181 /* Emulate poll() in terms of select() */
3182 fd_set read_set, write_set, err_set;
3183 int max_fd = 0;
3184 int i;
3185 struct timeval tv;
3186 int ready;
3187
3188 FD_ZERO (&read_set);
3189 FD_ZERO (&write_set);
3190 FD_ZERO (&err_set);
3191
3192 for (i = 0; i < n_fds; i++)
3193 {
3194 DBusPollFD *fdp = &fds[i];
3195
3196 if (fdp->events & _DBUS_POLLIN)
3197 FD_SET (fdp->fd, &read_set);
3198
3199 if (fdp->events & _DBUS_POLLOUT)
3200 FD_SET (fdp->fd, &write_set);
3201
3202 FD_SET (fdp->fd, &err_set);
3203
3204 max_fd = MAX (max_fd, fdp->fd);
3205 }
3206
3207 tv.tv_sec = timeout_milliseconds / 1000;
3208 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
3209
3210 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
3211 timeout_milliseconds < 0 ? NULL : &tv);
3212
3213 if (ready > 0)
3214 {
3215 for (i = 0; i < n_fds; i++)
3216 {
3217 DBusPollFD *fdp = &fds[i];
3218
3219 fdp->revents = 0;
3220
3221 if (FD_ISSET (fdp->fd, &read_set))
3222 fdp->revents |= _DBUS_POLLIN;
3223
3224 if (FD_ISSET (fdp->fd, &write_set))
3225 fdp->revents |= _DBUS_POLLOUT;
3226
3227 if (FD_ISSET (fdp->fd, &err_set))
3228 fdp->revents |= _DBUS_POLLERR;
3229 }
3230 }
3231
3232 return ready;
3233#endif
3234}
3235
3243void
3245 long *tv_usec)
3246{
3247#ifdef HAVE_MONOTONIC_CLOCK
3248 struct timespec ts;
3249 clock_gettime (CLOCK_MONOTONIC, &ts);
3250
3251 if (tv_sec)
3252 *tv_sec = ts.tv_sec;
3253 if (tv_usec)
3254 *tv_usec = ts.tv_nsec / 1000;
3255#else
3256 struct timeval t;
3257
3258 gettimeofday (&t, NULL);
3259
3260 if (tv_sec)
3261 *tv_sec = t.tv_sec;
3262 if (tv_usec)
3263 *tv_usec = t.tv_usec;
3264#endif
3265}
3266
3274void
3276 long *tv_usec)
3277{
3278 struct timeval t;
3279
3280 gettimeofday (&t, NULL);
3281
3282 if (tv_sec)
3283 *tv_sec = t.tv_sec;
3284 if (tv_usec)
3285 *tv_usec = t.tv_usec;
3286}
3287
3298 DBusError *error)
3299{
3300 const char *filename_c;
3301
3302 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3303
3304 filename_c = _dbus_string_get_const_data (filename);
3305
3306 if (mkdir (filename_c, 0700) < 0)
3307 {
3308 if (errno == EEXIST)
3309 return TRUE;
3310
3312 "Failed to create directory %s: %s\n",
3313 filename_c, _dbus_strerror (errno));
3314 return FALSE;
3315 }
3316 else
3317 return TRUE;
3318}
3319
3330 DBusError *error)
3331{
3332 const char *filename_c;
3333
3334 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3335
3336 filename_c = _dbus_string_get_const_data (filename);
3337
3338 if (mkdir (filename_c, 0700) < 0)
3339 {
3341 "Failed to create directory %s: %s\n",
3342 filename_c, _dbus_strerror (errno));
3343 return FALSE;
3344 }
3345 else
3346 return TRUE;
3347}
3348
3361 const DBusString *next_component)
3362{
3363 dbus_bool_t dir_ends_in_slash;
3364 dbus_bool_t file_starts_with_slash;
3365
3366 if (_dbus_string_get_length (dir) == 0 ||
3367 _dbus_string_get_length (next_component) == 0)
3368 return TRUE;
3369
3370 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3371 _dbus_string_get_length (dir) - 1);
3372
3373 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3374
3375 if (dir_ends_in_slash && file_starts_with_slash)
3376 {
3377 _dbus_string_shorten (dir, 1);
3378 }
3379 else if (!(dir_ends_in_slash || file_starts_with_slash))
3380 {
3381 if (!_dbus_string_append_byte (dir, '/'))
3382 return FALSE;
3383 }
3384
3385 return _dbus_string_copy (next_component, 0, dir,
3387}
3388
3390#define NANOSECONDS_PER_SECOND 1000000000
3392#define MICROSECONDS_PER_SECOND 1000000
3394#define MILLISECONDS_PER_SECOND 1000
3396#define NANOSECONDS_PER_MILLISECOND 1000000
3398#define MICROSECONDS_PER_MILLISECOND 1000
3399
3404void
3406{
3407#ifdef HAVE_NANOSLEEP
3408 struct timespec req;
3409 struct timespec rem;
3410
3411 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3412 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3413 rem.tv_sec = 0;
3414 rem.tv_nsec = 0;
3415
3416 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3417 req = rem;
3418#elif defined (HAVE_USLEEP)
3419 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3420#else /* ! HAVE_USLEEP */
3421 sleep (MAX (milliseconds / 1000, 1));
3422#endif
3423}
3424
3436 int n_bytes,
3437 DBusError *error)
3438{
3439 int old_len = _dbus_string_get_length (str);
3440 int fd;
3441 int result;
3442#ifdef HAVE_GETRANDOM
3443 char *buffer;
3444
3445 if (!_dbus_string_lengthen (str, n_bytes))
3446 {
3447 _DBUS_SET_OOM (error);
3448 return FALSE;
3449 }
3450
3451 buffer = _dbus_string_get_data_len (str, old_len, n_bytes);
3452 result = getrandom (buffer, n_bytes, GRND_NONBLOCK);
3453
3454 if (result == n_bytes)
3455 return TRUE;
3456
3457 _dbus_string_set_length (str, old_len);
3458#endif
3459
3460 /* note, urandom on linux will fall back to pseudorandom */
3461 fd = open ("/dev/urandom", O_RDONLY);
3462
3463 if (fd < 0)
3464 {
3465 dbus_set_error (error, _dbus_error_from_errno (errno),
3466 "Could not open /dev/urandom: %s",
3467 _dbus_strerror (errno));
3468 return FALSE;
3469 }
3470
3471 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3472
3473 result = _dbus_read (fd, str, n_bytes);
3474
3475 if (result != n_bytes)
3476 {
3477 if (result < 0)
3478 dbus_set_error (error, _dbus_error_from_errno (errno),
3479 "Could not read /dev/urandom: %s",
3480 _dbus_strerror (errno));
3481 else
3483 "Short read from /dev/urandom");
3484
3485 _dbus_close (fd, NULL);
3486 _dbus_string_set_length (str, old_len);
3487 return FALSE;
3488 }
3489
3490 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3491 n_bytes);
3492
3493 _dbus_close (fd, NULL);
3494
3495 return TRUE;
3496}
3497
3503void
3504_dbus_exit (int code)
3505{
3506 _exit (code);
3507}
3508
3517const char*
3518_dbus_strerror (int error_number)
3519{
3520 const char *msg;
3521
3522 msg = strerror (error_number);
3523 if (msg == NULL)
3524 msg = "unknown";
3525
3526 return msg;
3527}
3528
3532void
3534{
3535 signal (SIGPIPE, SIG_IGN);
3536}
3537
3545void
3547{
3548 int val;
3549
3550 val = fcntl (fd, F_GETFD, 0);
3551
3552 if (val < 0)
3553 return;
3554
3555 val |= FD_CLOEXEC;
3556
3557 fcntl (fd, F_SETFD, val);
3558}
3559
3567void
3569{
3570 int val;
3571
3572 val = fcntl (fd, F_GETFD, 0);
3573
3574 if (val < 0)
3575 return;
3576
3577 val &= ~FD_CLOEXEC;
3578
3579 fcntl (fd, F_SETFD, val);
3580}
3581
3591 DBusError *error)
3592{
3593 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3594
3595 again:
3596 if (close (fd) < 0)
3597 {
3598 if (errno == EINTR)
3599 goto again;
3600
3601 dbus_set_error (error, _dbus_error_from_errno (errno),
3602 "Could not close fd %d", fd);
3603 return FALSE;
3604 }
3605
3606 return TRUE;
3607}
3608
3617int
3619 DBusError *error)
3620{
3621 int new_fd;
3622
3623#ifdef F_DUPFD_CLOEXEC
3624 dbus_bool_t cloexec_done;
3625
3626 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3627 cloexec_done = new_fd >= 0;
3628
3629 if (new_fd < 0 && errno == EINVAL)
3630#endif
3631 {
3632 new_fd = fcntl(fd, F_DUPFD, 3);
3633 }
3634
3635 if (new_fd < 0) {
3636
3637 dbus_set_error (error, _dbus_error_from_errno (errno),
3638 "Could not duplicate fd %d", fd);
3639 return -1;
3640 }
3641
3642#ifdef F_DUPFD_CLOEXEC
3643 if (!cloexec_done)
3644#endif
3645 {
3647 }
3648
3649 return new_fd;
3650}
3651
3661 DBusError *error)
3662{
3663 return _dbus_set_fd_nonblocking (fd.fd, error);
3664}
3665
3666static dbus_bool_t
3667_dbus_set_fd_nonblocking (int fd,
3668 DBusError *error)
3669{
3670 int val;
3671
3672 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3673
3674 val = fcntl (fd, F_GETFL, 0);
3675 if (val < 0)
3676 {
3677 dbus_set_error (error, _dbus_error_from_errno (errno),
3678 "Failed to get flags from file descriptor %d: %s",
3679 fd, _dbus_strerror (errno));
3680 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3681 _dbus_strerror (errno));
3682 return FALSE;
3683 }
3684
3685 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3686 {
3687 dbus_set_error (error, _dbus_error_from_errno (errno),
3688 "Failed to set nonblocking flag of file descriptor %d: %s",
3689 fd, _dbus_strerror (errno));
3690 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3691 fd, _dbus_strerror (errno));
3692
3693 return FALSE;
3694 }
3695
3696 return TRUE;
3697}
3698
3704void
3706{
3707#if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3708 void *bt[500];
3709 int bt_size;
3710 int i;
3711 char **syms;
3712
3713 bt_size = backtrace (bt, 500);
3714
3715 syms = backtrace_symbols (bt, bt_size);
3716
3717 i = 0;
3718 while (i < bt_size)
3719 {
3720 /* don't use dbus_warn since it can _dbus_abort() */
3721 fprintf (stderr, " %s\n", syms[i]);
3722 ++i;
3723 }
3724 fflush (stderr);
3725
3726 free (syms);
3727#elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3728 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3729#else
3730 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3731#endif
3732}
3733
3748 DBusSocket *fd2,
3749 dbus_bool_t blocking,
3750 DBusError *error)
3751{
3752#ifdef HAVE_SOCKETPAIR
3753 int fds[2];
3754 int retval;
3755
3756#ifdef SOCK_CLOEXEC
3757 dbus_bool_t cloexec_done;
3758
3759 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3760 cloexec_done = retval >= 0;
3761
3762 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3763#endif
3764 {
3765 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3766 }
3767
3768 if (retval < 0)
3769 {
3770 dbus_set_error (error, _dbus_error_from_errno (errno),
3771 "Could not create full-duplex pipe");
3772 return FALSE;
3773 }
3774
3775 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3776
3777#ifdef SOCK_CLOEXEC
3778 if (!cloexec_done)
3779#endif
3780 {
3783 }
3784
3785 if (!blocking &&
3786 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3787 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3788 {
3789 dbus_set_error (error, _dbus_error_from_errno (errno),
3790 "Could not set full-duplex pipe nonblocking");
3791
3792 _dbus_close (fds[0], NULL);
3793 _dbus_close (fds[1], NULL);
3794
3795 return FALSE;
3796 }
3797
3798 fd1->fd = fds[0];
3799 fd2->fd = fds[1];
3800
3801 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3802 fd1->fd, fd2->fd);
3803
3804 return TRUE;
3805#else
3806 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3808 "_dbus_socketpair() not implemented on this OS");
3809 return FALSE;
3810#endif
3811}
3812
3821int
3823 va_list args)
3824{
3825 char static_buf[1024];
3826 int bufsize = sizeof (static_buf);
3827 int len;
3828 va_list args_copy;
3829
3830 va_copy (args_copy, args);
3831 len = vsnprintf (static_buf, bufsize, format, args_copy);
3832 va_end (args_copy);
3833
3834 /* If vsnprintf() returned non-negative, then either the string fits in
3835 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3836 * returns the number of characters that were needed, or this OS returns the
3837 * truncated length.
3838 *
3839 * We ignore the possibility that snprintf might just ignore the length and
3840 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3841 * If your libc is really that bad, come back when you have a better one. */
3842 if (len == bufsize)
3843 {
3844 /* This could be the truncated length (Tru64 and IRIX have this bug),
3845 * or the real length could be coincidentally the same. Which is it?
3846 * If vsnprintf returns the truncated length, we'll go to the slow
3847 * path. */
3848 va_copy (args_copy, args);
3849
3850 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3851 len = -1;
3852
3853 va_end (args_copy);
3854 }
3855
3856 /* If vsnprintf() returned negative, we have to do more work.
3857 * HP-UX returns negative. */
3858 while (len < 0)
3859 {
3860 char *buf;
3861
3862 bufsize *= 2;
3863
3864 buf = dbus_malloc (bufsize);
3865
3866 if (buf == NULL)
3867 return -1;
3868
3869 va_copy (args_copy, args);
3870 len = vsnprintf (buf, bufsize, format, args_copy);
3871 va_end (args_copy);
3872
3873 dbus_free (buf);
3874
3875 /* If the reported length is exactly the buffer size, round up to the
3876 * next size, in case vsnprintf has been returning the truncated
3877 * length */
3878 if (len == bufsize)
3879 len = -1;
3880 }
3881
3882 return len;
3883}
3884
3891const char*
3893{
3894 /* Protected by _DBUS_LOCK_sysdeps */
3895 static const char* tmpdir = NULL;
3896
3897 if (!_DBUS_LOCK (sysdeps))
3898 return NULL;
3899
3900 if (tmpdir == NULL)
3901 {
3902 /* TMPDIR is what glibc uses, then
3903 * glibc falls back to the P_tmpdir macro which
3904 * just expands to "/tmp"
3905 */
3906 if (tmpdir == NULL)
3907 tmpdir = getenv("TMPDIR");
3908
3909 /* These two env variables are probably
3910 * broken, but maybe some OS uses them?
3911 */
3912 if (tmpdir == NULL)
3913 tmpdir = getenv("TMP");
3914 if (tmpdir == NULL)
3915 tmpdir = getenv("TEMP");
3916
3917 /* And this is the sane fallback. */
3918 if (tmpdir == NULL)
3919 tmpdir = "/tmp";
3920 }
3921
3922 _DBUS_UNLOCK (sysdeps);
3923
3924 _dbus_assert(tmpdir != NULL);
3925
3926 return tmpdir;
3927}
3928
3929#if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3949static dbus_bool_t
3950_read_subprocess_line_argv (const char *progpath,
3951 dbus_bool_t path_fallback,
3952 const char * const *argv,
3953 DBusString *result,
3954 DBusError *error)
3955{
3956 int result_pipe[2] = { -1, -1 };
3957 int errors_pipe[2] = { -1, -1 };
3958 pid_t pid;
3959 int ret;
3960 int status;
3961 int orig_len;
3962
3963 dbus_bool_t retval;
3964 sigset_t new_set, old_set;
3965
3966 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3967 retval = FALSE;
3968
3969 /* We need to block any existing handlers for SIGCHLD temporarily; they
3970 * will cause waitpid() below to fail.
3971 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3972 */
3973 sigemptyset (&new_set);
3974 sigaddset (&new_set, SIGCHLD);
3975 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3976
3977 orig_len = _dbus_string_get_length (result);
3978
3979#define READ_END 0
3980#define WRITE_END 1
3981 if (pipe (result_pipe) < 0)
3982 {
3983 dbus_set_error (error, _dbus_error_from_errno (errno),
3984 "Failed to create a pipe to call %s: %s",
3985 progpath, _dbus_strerror (errno));
3986 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3987 progpath, _dbus_strerror (errno));
3988 goto out;
3989 }
3990 if (pipe (errors_pipe) < 0)
3991 {
3992 dbus_set_error (error, _dbus_error_from_errno (errno),
3993 "Failed to create a pipe to call %s: %s",
3994 progpath, _dbus_strerror (errno));
3995 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3996 progpath, _dbus_strerror (errno));
3997 goto out;
3998 }
3999
4000 /* Make sure our output buffers aren't redundantly printed by both the
4001 * parent and the child */
4002 fflush (stdout);
4003 fflush (stderr);
4004
4005 pid = fork ();
4006 if (pid < 0)
4007 {
4008 dbus_set_error (error, _dbus_error_from_errno (errno),
4009 "Failed to fork() to call %s: %s",
4010 progpath, _dbus_strerror (errno));
4011 _dbus_verbose ("Failed to fork() to call %s: %s\n",
4012 progpath, _dbus_strerror (errno));
4013 goto out;
4014 }
4015
4016 if (pid == 0)
4017 {
4018 /* child process */
4019 const char *error_str;
4020
4021 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
4022 {
4023 int saved_errno = errno;
4024
4025 /* Try to write details into the pipe, but don't bother
4026 * trying too hard (no retry loop). */
4027
4028 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
4029 write (errors_pipe[WRITE_END], ": ", 2) < 0)
4030 {
4031 /* ignore, not much we can do */
4032 }
4033
4034 error_str = _dbus_strerror (saved_errno);
4035
4036 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
4037 {
4038 /* ignore, not much we can do */
4039 }
4040
4041 _exit (1);
4042 }
4043
4044 /* set-up stdXXX */
4045 close (result_pipe[READ_END]);
4046 close (errors_pipe[READ_END]);
4047
4048 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
4049 _exit (1);
4050 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
4051 _exit (1);
4052
4053 _dbus_close_all ();
4054
4055 sigprocmask (SIG_SETMASK, &old_set, NULL);
4056
4057 /* If it looks fully-qualified, try execv first */
4058 if (progpath[0] == '/')
4059 {
4060 execv (progpath, (char * const *) argv);
4061 /* Ok, that failed. Now if path_fallback is given, let's
4062 * try unqualified. This is mostly a hack to work
4063 * around systems which ship dbus-launch in /usr/bin
4064 * but everything else in /bin (because dbus-launch
4065 * depends on X11).
4066 */
4067 if (path_fallback)
4068 /* We must have a slash, because we checked above */
4069 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
4070 }
4071 else
4072 execvp (progpath, (char * const *) argv);
4073
4074 /* still nothing, we failed */
4075 _exit (1);
4076 }
4077
4078 /* parent process */
4079 close (result_pipe[WRITE_END]);
4080 close (errors_pipe[WRITE_END]);
4081 result_pipe[WRITE_END] = -1;
4082 errors_pipe[WRITE_END] = -1;
4083
4084 ret = 0;
4085 do
4086 {
4087 ret = _dbus_read (result_pipe[READ_END], result, 1024);
4088 }
4089 while (ret > 0);
4090
4091 /* reap the child process to avoid it lingering as zombie */
4092 do
4093 {
4094 ret = waitpid (pid, &status, 0);
4095 }
4096 while (ret == -1 && errno == EINTR);
4097
4098 /* We succeeded if the process exited with status 0 and
4099 anything was read */
4100 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
4101 {
4102 /* The process ended with error */
4103 DBusString error_message;
4104 if (!_dbus_string_init (&error_message))
4105 {
4106 _DBUS_SET_OOM (error);
4107 goto out;
4108 }
4109
4110 ret = 0;
4111 do
4112 {
4113 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
4114 }
4115 while (ret > 0);
4116
4117 _dbus_string_set_length (result, orig_len);
4118 if (_dbus_string_get_length (&error_message) > 0)
4120 "%s terminated abnormally with the following error: %s",
4121 progpath, _dbus_string_get_data (&error_message));
4122 else
4124 "%s terminated abnormally without any error message",
4125 progpath);
4126 goto out;
4127 }
4128
4129 retval = TRUE;
4130
4131 out:
4132 sigprocmask (SIG_SETMASK, &old_set, NULL);
4133
4134 _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
4135
4136 if (result_pipe[0] != -1)
4137 close (result_pipe[0]);
4138 if (result_pipe[1] != -1)
4139 close (result_pipe[1]);
4140 if (errors_pipe[0] != -1)
4141 close (errors_pipe[0]);
4142 if (errors_pipe[1] != -1)
4143 close (errors_pipe[1]);
4144
4145 return retval;
4146}
4147#endif
4148
4163 DBusString *address,
4164 DBusError *error)
4165{
4166#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
4167 static const char arg_dbus_launch[] = "dbus-launch";
4168 static const char arg_autolaunch[] = "--autolaunch";
4169 static const char arg_binary_syntax[] = "--binary-syntax";
4170 static const char arg_close_stderr[] = "--close-stderr";
4171
4172 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
4173 * but that's done elsewhere, and if it worked, this function wouldn't
4174 * be called.) */
4175 const char *display;
4176 const char *progpath;
4177 const char *argv[6];
4178 int i;
4179 DBusString uuid;
4180 dbus_bool_t retval;
4181
4182 if (_dbus_check_setuid ())
4183 {
4185 "Unable to autolaunch when setuid");
4186 return FALSE;
4187 }
4188
4189 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4190 retval = FALSE;
4191
4192 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
4193 * dbus-launch-x11 is just going to fail. Rather than trying to
4194 * run it, we might as well bail out early with a nice error.
4195 *
4196 * This is not strictly true in a world where the user bus exists,
4197 * because dbus-launch --autolaunch knows how to connect to that -
4198 * but if we were going to connect to the user bus, we'd have done
4199 * so before trying autolaunch: in any case. */
4200 display = _dbus_getenv ("DISPLAY");
4201
4202 if (display == NULL || display[0] == '\0')
4203 {
4205 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
4206 return FALSE;
4207 }
4208
4209 if (!_dbus_string_init (&uuid))
4210 {
4211 _DBUS_SET_OOM (error);
4212 return FALSE;
4213 }
4214
4215 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
4216 {
4217 goto out;
4218 }
4219
4220#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4221 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
4222
4223 if (progpath == NULL)
4224#endif
4225 progpath = DBUS_BINDIR "/dbus-launch";
4226 /*
4227 * argv[0] is always dbus-launch, that's the name what we'll
4228 * get from /proc, or ps(1), regardless what the progpath is,
4229 * see fd.o#69716
4230 */
4231 i = 0;
4232 argv[i] = arg_dbus_launch;
4233 ++i;
4234 argv[i] = arg_autolaunch;
4235 ++i;
4236 argv[i] = _dbus_string_get_data (&uuid);
4237 ++i;
4238 argv[i] = arg_binary_syntax;
4239 ++i;
4240 argv[i] = arg_close_stderr;
4241 ++i;
4242 argv[i] = NULL;
4243 ++i;
4244
4245 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4246
4247 retval = _read_subprocess_line_argv (progpath,
4248 TRUE,
4249 argv, address, error);
4250
4251 out:
4252 _dbus_string_free (&uuid);
4253 return retval;
4254#else
4256 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
4257 "set your DBUS_SESSION_BUS_ADDRESS instead");
4258 return FALSE;
4259#endif
4260}
4261
4282 dbus_bool_t create_if_not_found,
4283 DBusError *error)
4284{
4285 DBusError our_error = DBUS_ERROR_INIT;
4286 DBusError etc_error = DBUS_ERROR_INIT;
4287 DBusString filename;
4288 dbus_bool_t b;
4289
4290 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4291
4292 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
4293 if (b)
4294 return TRUE;
4295
4296 /* Fallback to the system machine ID */
4297 _dbus_string_init_const (&filename, "/etc/machine-id");
4298 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
4299
4300 if (b)
4301 {
4302 if (create_if_not_found)
4303 {
4304 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
4305 * complain if that isn't possible for whatever reason */
4306 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4307 _dbus_write_uuid_file (&filename, machine_id, NULL);
4308 }
4309
4310 dbus_error_free (&our_error);
4311 return TRUE;
4312 }
4313
4314 if (!create_if_not_found)
4315 {
4316 dbus_set_error (error, etc_error.name,
4317 "D-Bus library appears to be incorrectly set up: "
4318 "see the manual page for dbus-uuidgen to correct "
4319 "this issue. (%s; %s)",
4320 our_error.message, etc_error.message);
4321 dbus_error_free (&our_error);
4322 dbus_error_free (&etc_error);
4323 return FALSE;
4324 }
4325
4326 dbus_error_free (&our_error);
4327 dbus_error_free (&etc_error);
4328
4329 /* if none found, try to make a new one */
4330 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4331
4332 if (!_dbus_generate_uuid (machine_id, error))
4333 return FALSE;
4334
4335 return _dbus_write_uuid_file (&filename, machine_id, error);
4336}
4337
4347 const char *launchd_env_var,
4348 DBusError *error)
4349{
4350#ifdef DBUS_ENABLE_LAUNCHD
4351 char *argv[4];
4352 int i;
4353
4354 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4355
4356 if (_dbus_check_setuid ())
4357 {
4359 "Unable to find launchd socket when setuid");
4360 return FALSE;
4361 }
4362
4363 i = 0;
4364 argv[i] = "launchctl";
4365 ++i;
4366 argv[i] = "getenv";
4367 ++i;
4368 argv[i] = (char*)launchd_env_var;
4369 ++i;
4370 argv[i] = NULL;
4371 ++i;
4372
4373 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4374
4375 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4376 {
4377 return FALSE;
4378 }
4379
4380 /* no error, but no result either */
4381 if (_dbus_string_get_length(socket_path) == 0)
4382 {
4383 return FALSE;
4384 }
4385
4386 /* strip the carriage-return */
4387 _dbus_string_shorten(socket_path, 1);
4388 return TRUE;
4389#else /* DBUS_ENABLE_LAUNCHD */
4391 "can't lookup socket from launchd; launchd support not compiled in");
4392 return FALSE;
4393#endif
4394}
4395
4396#ifdef DBUS_ENABLE_LAUNCHD
4397static dbus_bool_t
4398_dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4399{
4400 dbus_bool_t valid_socket;
4401 DBusString socket_path;
4402
4403 if (_dbus_check_setuid ())
4404 {
4406 "Unable to find launchd socket when setuid");
4407 return FALSE;
4408 }
4409
4410 if (!_dbus_string_init (&socket_path))
4411 {
4412 _DBUS_SET_OOM (error);
4413 return FALSE;
4414 }
4415
4416 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4417
4418 if (dbus_error_is_set(error))
4419 {
4420 _dbus_string_free(&socket_path);
4421 return FALSE;
4422 }
4423
4424 if (!valid_socket)
4425 {
4426 dbus_set_error(error, "no socket path",
4427 "launchd did not provide a socket path, "
4428 "verify that org.freedesktop.dbus-session.plist is loaded!");
4429 _dbus_string_free(&socket_path);
4430 return FALSE;
4431 }
4432 if (!_dbus_string_append (address, "unix:path="))
4433 {
4434 _DBUS_SET_OOM (error);
4435 _dbus_string_free(&socket_path);
4436 return FALSE;
4437 }
4438 if (!_dbus_string_copy (&socket_path, 0, address,
4439 _dbus_string_get_length (address)))
4440 {
4441 _DBUS_SET_OOM (error);
4442 _dbus_string_free(&socket_path);
4443 return FALSE;
4444 }
4445
4446 _dbus_string_free(&socket_path);
4447 return TRUE;
4448}
4449#endif
4450
4451static dbus_bool_t
4452_dbus_lookup_user_bus (dbus_bool_t *supported,
4453 DBusString *address,
4454 DBusError *error)
4455{
4456 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4457 dbus_bool_t ret = FALSE;
4458 struct stat stbuf;
4459 DBusString user_bus_path;
4460
4461 if (runtime_dir == NULL)
4462 {
4463 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4464 *supported = FALSE;
4465 return TRUE; /* Cannot use it, but not an error */
4466 }
4467
4468 if (!_dbus_string_init (&user_bus_path))
4469 {
4470 _DBUS_SET_OOM (error);
4471 return FALSE;
4472 }
4473
4474 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4475 {
4476 _DBUS_SET_OOM (error);
4477 goto out;
4478 }
4479
4480 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4481 {
4482 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4483 _dbus_strerror (errno));
4484 *supported = FALSE;
4485 ret = TRUE; /* Cannot use it, but not an error */
4486 goto out;
4487 }
4488
4489 if (stbuf.st_uid != getuid ())
4490 {
4491 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4492 (long) stbuf.st_uid, (long) getuid ());
4493 *supported = FALSE;
4494 ret = TRUE; /* Cannot use it, but not an error */
4495 goto out;
4496 }
4497
4498 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4499 {
4500 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4501 (long) stbuf.st_mode);
4502 *supported = FALSE;
4503 ret = TRUE; /* Cannot use it, but not an error */
4504 goto out;
4505 }
4506
4507 if (!_dbus_string_append (address, "unix:path=") ||
4508 !_dbus_address_append_escaped (address, &user_bus_path))
4509 {
4510 _DBUS_SET_OOM (error);
4511 goto out;
4512 }
4513
4514 *supported = TRUE;
4515 ret = TRUE;
4516
4517out:
4518 _dbus_string_free (&user_bus_path);
4519 return ret;
4520}
4521
4543 DBusString *address,
4544 DBusError *error)
4545{
4546#ifdef DBUS_ENABLE_LAUNCHD
4547 *supported = TRUE;
4548 return _dbus_lookup_session_address_launchd (address, error);
4549#else
4550 *supported = FALSE;
4551
4552 if (!_dbus_lookup_user_bus (supported, address, error))
4553 return FALSE;
4554 else if (*supported)
4555 return TRUE;
4556
4557 /* On non-Mac Unix platforms, if the session address isn't already
4558 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4559 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4560 * autolaunch: global default; see init_session_address in
4561 * dbus/dbus-bus.c. */
4562 return TRUE;
4563#endif
4564}
4565
4573void
4575{
4577}
4578
4594 DBusCredentials *credentials)
4595{
4596 DBusString homedir;
4597 DBusString dotdir;
4598 dbus_uid_t uid;
4599
4600 _dbus_assert (credentials != NULL);
4602
4603 if (!_dbus_string_init (&homedir))
4604 return FALSE;
4605
4606 uid = _dbus_credentials_get_unix_uid (credentials);
4608
4609 if (!_dbus_homedir_from_uid (uid, &homedir))
4610 goto failed;
4611
4612#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4613 {
4614 const char *override;
4615
4616 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4617 if (override != NULL && *override != '\0')
4618 {
4619 _dbus_string_set_length (&homedir, 0);
4620 if (!_dbus_string_append (&homedir, override))
4621 goto failed;
4622
4623 _dbus_verbose ("Using fake homedir for testing: %s\n",
4624 _dbus_string_get_const_data (&homedir));
4625 }
4626 else
4627 {
4628 /* Not strictly thread-safe, but if we fail at thread-safety here,
4629 * the worst that will happen is some extra warnings. */
4630 static dbus_bool_t already_warned = FALSE;
4631 if (!already_warned)
4632 {
4633 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4634 _dbus_string_get_const_data (&homedir));
4635 already_warned = TRUE;
4636 }
4637 }
4638 }
4639#endif
4640
4641 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4642 if (!_dbus_concat_dir_and_file (&homedir,
4643 &dotdir))
4644 goto failed;
4645
4646 if (!_dbus_string_copy (&homedir, 0,
4647 directory, _dbus_string_get_length (directory))) {
4648 goto failed;
4649 }
4650
4651 _dbus_string_free (&homedir);
4652 return TRUE;
4653
4654 failed:
4655 _dbus_string_free (&homedir);
4656 return FALSE;
4657}
4658
4659/* Documented in dbus-sysdeps-win.c, does nothing on Unix */
4661_dbus_daemon_unpublish_session_bus_address (void)
4662{
4663 return TRUE;
4664}
4665
4674{
4675 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4676 * EWOULDBLOCK are numerically equal, which is permitted as described by
4677 * errno(3).
4678 */
4679#if EAGAIN == EWOULDBLOCK
4680 return e == EAGAIN;
4681#else
4682 return e == EAGAIN || e == EWOULDBLOCK;
4683#endif
4684}
4685
4695 DBusError *error)
4696{
4697 const char *filename_c;
4698
4699 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4700
4701 filename_c = _dbus_string_get_const_data (filename);
4702
4703 if (rmdir (filename_c) != 0)
4704 {
4706 "Failed to remove directory %s: %s\n",
4707 filename_c, _dbus_strerror (errno));
4708 return FALSE;
4709 }
4710
4711 return TRUE;
4712}
4713
4723{
4724#ifdef SCM_RIGHTS
4725 union {
4726 struct sockaddr sa;
4727 struct sockaddr_storage storage;
4728 struct sockaddr_un un;
4729 } sa_buf;
4730
4731 socklen_t sa_len = sizeof(sa_buf);
4732
4733 _DBUS_ZERO(sa_buf);
4734
4735 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4736 return FALSE;
4737
4738 return sa_buf.sa.sa_family == AF_UNIX;
4739
4740#else
4741 return FALSE;
4742
4743#endif
4744}
4745
4746/*
4747 * Similar to Solaris fdwalk(3), but without the ability to stop iteration,
4748 * and may call func for integers that are not actually valid fds.
4749 */
4750static void
4751act_on_fds_3_and_up (void (*func) (int fd))
4752{
4753 int maxfds, i;
4754
4755#if defined(__linux__) && defined(__GLIBC__)
4756 DIR *d;
4757
4758 /* On Linux we can optimize this a bit if /proc is available. If it
4759 isn't available, fall back to the brute force way. */
4760
4761 d = opendir ("/proc/self/fd");
4762 if (d)
4763 {
4764 for (;;)
4765 {
4766 struct dirent *de;
4767 int fd;
4768 long l;
4769 char *e = NULL;
4770
4771 de = readdir (d);
4772 if (!de)
4773 break;
4774
4775 if (de->d_name[0] == '.')
4776 continue;
4777
4778 errno = 0;
4779 l = strtol (de->d_name, &e, 10);
4780 if (errno != 0 || e == NULL || *e != '\0')
4781 continue;
4782
4783 fd = (int) l;
4784 if (fd < 3)
4785 continue;
4786
4787 if (fd == dirfd (d))
4788 continue;
4789
4790 func (fd);
4791 }
4792
4793 closedir (d);
4794 return;
4795 }
4796#endif
4797
4798 maxfds = sysconf (_SC_OPEN_MAX);
4799
4800 /* Pick something reasonable if for some reason sysconf says
4801 * unlimited.
4802 */
4803 if (maxfds < 0)
4804 maxfds = 1024;
4805
4806 /* close all inherited fds */
4807 for (i = 3; i < maxfds; i++)
4808 func (i);
4809}
4810
4811/* Some library implementations of closefrom() are not async-signal-safe,
4812 * and we call _dbus_close_all() after forking, so we only do this on
4813 * operating systems where we know that closefrom() is a system call */
4814#if defined(HAVE_CLOSEFROM) && ( \
4815 defined(__FreeBSD__) || \
4816 defined(__NetBSD__) || \
4817 defined(__OpenBSD__) || \
4818 defined(__sun__) && defined(F_CLOSEFROM) \
4819)
4820#define CLOSEFROM_SIGNAL_SAFE 1
4821#else
4822#define CLOSEFROM_SIGNAL_SAFE 0
4823static void
4824close_ignore_error (int fd)
4825{
4826 close (fd);
4827}
4828#endif
4829
4834void
4836{
4837#ifdef HAVE_CLOSE_RANGE
4838 if (close_range (3, INT_MAX, 0) == 0)
4839 return;
4840#endif
4841
4842#if CLOSEFROM_SIGNAL_SAFE
4843 closefrom (3);
4844#else
4845 act_on_fds_3_and_up (close_ignore_error);
4846#endif
4847}
4848
4853void
4855{
4856#if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC)
4857 if (close_range (3, INT_MAX, CLOSE_RANGE_CLOEXEC) == 0)
4858 return;
4859#endif
4860
4861 act_on_fds_3_and_up (_dbus_fd_set_close_on_exec);
4862}
4863
4875{
4876 /* TODO: get __libc_enable_secure exported from glibc.
4877 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4878 */
4879#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4880 {
4881 /* See glibc/include/unistd.h */
4882 extern int __libc_enable_secure;
4883 return __libc_enable_secure;
4884 }
4885#elif defined(HAVE_ISSETUGID)
4886 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4887 return issetugid ();
4888#else
4889 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4890 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4891
4892 /* We call into this function from _dbus_threads_init_platform_specific()
4893 * to make sure these are initialized before we start threading. */
4894 static dbus_bool_t check_setuid_initialised;
4895 static dbus_bool_t is_setuid;
4896
4897 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4898 {
4899#ifdef HAVE_GETRESUID
4900 if (getresuid (&ruid, &euid, &suid) != 0 ||
4901 getresgid (&rgid, &egid, &sgid) != 0)
4902#endif /* HAVE_GETRESUID */
4903 {
4904 suid = ruid = getuid ();
4905 sgid = rgid = getgid ();
4906 euid = geteuid ();
4907 egid = getegid ();
4908 }
4909
4910 check_setuid_initialised = TRUE;
4911 is_setuid = (ruid != euid || ruid != suid ||
4912 rgid != egid || rgid != sgid);
4913
4914 }
4915 return is_setuid;
4916#endif
4917}
4918
4928 DBusString *address,
4929 DBusError *error)
4930{
4931 union {
4932 struct sockaddr sa;
4933 struct sockaddr_storage storage;
4934 struct sockaddr_un un;
4935 struct sockaddr_in ipv4;
4936 struct sockaddr_in6 ipv6;
4937 } socket;
4938 char hostip[INET6_ADDRSTRLEN];
4939 socklen_t size = sizeof (socket);
4940 DBusString path_str;
4941 const char *family_name = NULL;
4942 dbus_uint16_t port;
4943
4944 if (getsockname (fd.fd, &socket.sa, &size))
4945 goto err;
4946
4947 switch (socket.sa.sa_family)
4948 {
4949 case AF_UNIX:
4950 if (socket.un.sun_path[0]=='\0')
4951 {
4952 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4953 if (_dbus_string_append (address, "unix:abstract=") &&
4954 _dbus_address_append_escaped (address, &path_str))
4955 {
4956 return TRUE;
4957 }
4958 else
4959 {
4960 _DBUS_SET_OOM (error);
4961 return FALSE;
4962 }
4963 }
4964 else
4965 {
4966 _dbus_string_init_const (&path_str, socket.un.sun_path);
4967 if (_dbus_string_append (address, "unix:path=") &&
4968 _dbus_address_append_escaped (address, &path_str))
4969 {
4970 return TRUE;
4971 }
4972 else
4973 {
4974 _DBUS_SET_OOM (error);
4975 return FALSE;
4976 }
4977 }
4978 /* not reached */
4979 break;
4980
4981 case AF_INET:
4982#ifdef AF_INET6
4983 case AF_INET6:
4984#endif
4985 _dbus_string_init_const (&path_str, hostip);
4986
4987 if (_dbus_inet_sockaddr_to_string (&socket, size, hostip, sizeof (hostip),
4988 &family_name, &port, error))
4989 {
4990 if (_dbus_string_append_printf (address, "tcp:family=%s,port=%u,host=",
4991 family_name, port) &&
4992 _dbus_address_append_escaped (address, &path_str))
4993 {
4994 return TRUE;
4995 }
4996 else
4997 {
4998 _DBUS_SET_OOM (error);
4999 return FALSE;
5000 }
5001 }
5002 else
5003 {
5004 return FALSE;
5005 }
5006 /* not reached */
5007 break;
5008
5009 default:
5010 dbus_set_error (error,
5011 _dbus_error_from_errno (EINVAL),
5012 "Failed to read address from socket: Unknown socket type.");
5013 return FALSE;
5014 }
5015 err:
5016 dbus_set_error (error,
5017 _dbus_error_from_errno (errno),
5018 "Failed to read address from socket: %s",
5019 _dbus_strerror (errno));
5020 return FALSE;
5021}
5022
5023int
5024_dbus_save_socket_errno (void)
5025{
5026 return errno;
5027}
5028
5029void
5030_dbus_restore_socket_errno (int saved_errno)
5031{
5032 errno = saved_errno;
5033}
5034
5035static const char *syslog_tag = "dbus";
5036#ifdef HAVE_SYSLOG_H
5037static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
5038#endif
5039
5054void
5055_dbus_init_system_log (const char *tag,
5056 DBusLogFlags flags)
5057{
5058 /* We never want to turn off logging completely */
5059 _dbus_assert (
5060 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
5061
5062 syslog_tag = tag;
5063
5064#ifdef HAVE_SYSLOG_H
5065 log_flags = flags;
5066
5067 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5068 openlog (tag, LOG_PID, LOG_DAEMON);
5069#endif
5070}
5071
5079void
5080_dbus_logv (DBusSystemLogSeverity severity,
5081 const char *msg,
5082 va_list args)
5083{
5084 va_list tmp;
5085#ifdef HAVE_SYSLOG_H
5086 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5087 {
5088 int flags;
5089 switch (severity)
5090 {
5091 case DBUS_SYSTEM_LOG_INFO:
5092 flags = LOG_DAEMON | LOG_INFO;
5093 break;
5094 case DBUS_SYSTEM_LOG_WARNING:
5095 flags = LOG_DAEMON | LOG_WARNING;
5096 break;
5097 case DBUS_SYSTEM_LOG_SECURITY:
5098 flags = LOG_AUTH | LOG_NOTICE;
5099 break;
5100 case DBUS_SYSTEM_LOG_ERROR:
5101 flags = LOG_DAEMON|LOG_CRIT;
5102 break;
5103 default:
5104 _dbus_assert_not_reached ("invalid log severity");
5105 }
5106
5107 va_copy (tmp, args);
5108 vsyslog (flags, msg, tmp);
5109 va_end (tmp);
5110 }
5111
5112 /* If we don't have syslog.h, we always behave as though stderr was in
5113 * the flags */
5114 if (log_flags & DBUS_LOG_FLAGS_STDERR)
5115#endif
5116 {
5117 va_copy (tmp, args);
5118 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
5119 vfprintf (stderr, msg, tmp);
5120 fputc ('\n', stderr);
5121 va_end (tmp);
5122 }
5123}
5124
5125/*
5126 * Return the low-level representation of a socket error, as used by
5127 * cross-platform socket APIs like inet_ntop(), send() and recv(). This
5128 * is the standard errno on Unix, but is WSAGetLastError() on Windows.
5129 *
5130 * Some libdbus internal functions copy this into errno, but with
5131 * hindsight that was probably a design flaw.
5132 */
5133int
5134_dbus_get_low_level_socket_errno (void)
5135{
5136 return errno;
5137}
5138
5139/* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_address_append_escaped(DBusString *escaped, const DBusString *unescaped)
Appends an escaped version of one string to another string, using the D-Bus address escaping mechanis...
Definition: dbus-address.c:109
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
dbus_uid_t _dbus_credentials_get_unix_uid(DBusCredentials *credentials)
Gets the UNIX user ID in the credentials, or DBUS_UID_UNSET if the credentials object doesn't contain...
dbus_bool_t _dbus_credentials_add_linux_security_label(DBusCredentials *credentials, const char *label)
Add a Linux security label, as used by LSMs such as SELinux, Smack and AppArmor, to the credentials.
void _dbus_credentials_take_unix_gids(DBusCredentials *credentials, dbus_gid_t *gids, size_t n_gids)
Add UNIX group IDs to the credentials, replacing any group IDs that might already have been present.
dbus_bool_t _dbus_credentials_add_unix_uid(DBusCredentials *credentials, dbus_uid_t uid)
Add a UNIX user ID to the credentials.
dbus_bool_t _dbus_credentials_add_pid(DBusCredentials *credentials, dbus_pid_t pid)
Add a UNIX process ID to the credentials.
dbus_bool_t _dbus_credentials_add_adt_audit_data(DBusCredentials *credentials, void *audit_data, dbus_int32_t size)
Add ADT audit data to the credentials.
dbus_bool_t _dbus_credentials_are_anonymous(DBusCredentials *credentials)
Checks whether a credentials object contains a user identity.
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:64
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:245
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:190
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:356
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:213
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:331
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define READ_END
Helps remember which end of the pipe is which.
#define WRITE_END
Helps remember which end of the pipe is which.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:601
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:396
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
dbus_bool_t _dbus_homedir_from_uid(dbus_uid_t uid, DBusString *homedir)
Gets the home directory for the given user.
Definition: dbus-userdb.c:466
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
#define _DBUS_INT32_MAX
Maximum value of type "int32".
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:679
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:273
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:694
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:594
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:59
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:60
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:454
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:847
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:980
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1345
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:139
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:535
char * _dbus_string_get_data(DBusString *str)
Gets the raw character buffer from the string.
Definition: dbus-string.c:496
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:825
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:805
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
Definition: dbus-string.c:784
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:403
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1190
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1147
const char * _dbus_string_get_const_data_len(const DBusString *str, int start, int len)
const version of _dbus_string_get_data_len().
Definition: dbus-string.c:559
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:513
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
Definition: dbus-string.c:607
void _dbus_fd_clear_close_on_exec(int fd)
Sets the file descriptor to not be close-on-exec.
void _dbus_fd_set_all_close_on_exec(void)
Sets all file descriptors except the first three (i.e.
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
int _dbus_write(int fd, const DBusString *buffer, int start, int len)
Thin wrapper around the write() system call that writes a part of a DBusString and handles EINTR for ...
int _dbus_write_two(int fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write() but will use writev() if possible to write both buffers in sequence.
dbus_bool_t _dbus_lookup_launchd_socket(DBusString *socket_path, const char *launchd_env_var, DBusError *error)
quries launchd for a specific env var which holds the socket path.
int _dbus_listen_systemd_sockets(DBusSocket **fds, DBusError *error)
Acquires one or more sockets passed in from systemd.
dbus_bool_t _dbus_append_address_from_socket(DBusSocket fd, DBusString *address, DBusError *error)
Read the address from the socket and append it to the string.
dbus_bool_t _dbus_user_info_fill(DBusUserInfo *info, const DBusString *username, DBusError *error)
Gets user info for the given username.
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
int _dbus_read(int fd, DBusString *buffer, int count)
Thin wrapper around the read() system call that appends the data it reads to the DBusString buffer.
dbus_bool_t _dbus_ensure_standard_fds(DBusEnsureStandardFdsFlags flags, const char **error_str_p)
Ensure that the standard file descriptors stdin, stdout and stderr are open, by opening /dev/null if ...
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
dbus_bool_t _dbus_user_info_fill_uid(DBusUserInfo *info, dbus_uid_t uid, DBusError *error)
Gets user info for the given user ID.
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
dbus_bool_t _dbus_read_local_machine_uuid(DBusGUID *machine_id, dbus_bool_t create_if_not_found, DBusError *error)
Reads the uuid of the machine we're running on from the dbus configuration.
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:429
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:137
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted)
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:135
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
void _dbus_exit(int code)
Exit the process, returning the given value.
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:431
dbus_bool_t _dbus_socket_can_pass_unix_fd(DBusSocket fd)
Checks whether file descriptors may be passed via the socket.
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Like _dbus_write(), but only supports sockets and is thus available on Windows.
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:139
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, unsigned int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
dbus_bool_t _dbus_append_keyring_directory_for_credentials(DBusString *directory, DBusCredentials *credentials)
Appends the directory in which a keyring for the given credentials should be stored.
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:144
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_read_credentials_socket(DBusSocket client_fd, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:142
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:197
DBusSocket _dbus_listen_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket fd, DBusError *error)
Sets a file descriptor to be nonblocking.
dbus_bool_t _dbus_lookup_session_address(dbus_bool_t *supported, DBusString *address, DBusError *error)
Determines the address of the session bus by querying a platform-specific method.
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib.
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:146
dbus_bool_t _dbus_check_dir_is_private_to_user(DBusString *dir, DBusError *error)
Checks to make sure the given directory is private to the user.
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:425
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, const char **retfamily, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
dbus_bool_t _dbus_send_credentials_socket(DBusSocket server_fd, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
dbus_uid_t _dbus_getuid(void)
Gets our UID.
dbus_bool_t _dbus_credentials_add_from_current_process(DBusCredentials *credentials)
Adds the most important credentials of the current process (the uid and pid) to the passed-in credent...
dbus_bool_t _dbus_close_socket(DBusSocket *fd, DBusError *error)
Closes a socket and invalidates it.
DBusSocket _dbus_connect_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and connects it to the UNIX domain socket at the given path.
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with.
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:153
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
dbus_bool_t _dbus_delete_directory(const DBusString *filename, DBusError *error)
Removes a directory; Directory must be empty.
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:151
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
dbus_bool_t _dbus_get_autolaunch_address(const char *scope, DBusString *address, DBusError *error)
Returns the address of a new session bus.
int _dbus_write_socket_two(DBusSocket fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write_two() but only works on sockets and is thus available on Windows.
dbus_bool_t _dbus_concat_dir_and_file(DBusString *dir, const DBusString *next_component)
Appends the given filename to the given directory.
DBusSocket _dbus_connect_exec(const char *path, char *const argv[], DBusError *error)
Creates a UNIX domain socket and connects it to the specified process to execute.
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
void _dbus_init_system_log(const char *tag, DBusLogFlags flags)
Initialize the system log.
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
#define _DBUS_MAX_SUN_PATH_LENGTH
Maximum length of the path to a UNIX domain socket, sockaddr_un::sun_path member.
Definition: dbus-sysdeps.h:745
dbus_bool_t _dbus_append_user_from_current_process(DBusString *str)
Append to the string the identity we would like to have when we authenticate, on UNIX this is the cur...
void _dbus_flush_caches(void)
Called when the bus daemon is signaled to reload its configuration; any caches should be nuked.
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR,...
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:149
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:37
unsigned short dbus_uint16_t
A 16-bit unsigned integer on all platforms.
int dbus_int32_t
A 32-bit signed integer on all platforms.
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:323
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:327
Object representing an exception.
Definition: dbus-errors.h:51
const char * name
public error name field
Definition: dbus-errors.h:52
const char * message
public error message field
Definition: dbus-errors.h:53
A node in a linked list.
Definition: dbus-list.h:37
short events
Events to poll for.
Definition: dbus-sysdeps.h:420
short revents
Events that occurred.
Definition: dbus-sysdeps.h:421
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:419
Socket interface.
Definition: dbus-sysdeps.h:181
Information about a UNIX user.
int n_group_ids
Size of group IDs array.
dbus_uid_t uid
UID.
char * homedir
Home directory.
dbus_gid_t * group_ids
Groups IDs, including above primary group.
char * username
Username.
dbus_gid_t primary_gid
GID.
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...