D-Bus 1.16.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 !defined(HAVE_STDATOMIC_H) && !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 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
381#ifdef HAVE_UNIX_FD_PASSING
400static dbus_bool_t
401_dbus_socket_unpack_or_close_scm_rights (struct msghdr *m,
402 int *fds,
403 unsigned int *n_fds)
404{
405 struct cmsghdr *cm;
406 dbus_bool_t found = FALSE;
407
408 for (cm = CMSG_FIRSTHDR (m); cm != NULL; cm = CMSG_NXTHDR (m, cm))
409 {
410 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
411 {
412 size_t i;
413 int *payload = (int *) (void *) CMSG_DATA (cm);
414 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
415 size_t payload_len_fds;
416 size_t fds_to_use;
417
418 /* Every unsigned int fits in a size_t without truncation, so
419 * casting (size_t) *n_fds is OK */
420 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
421
422 if ((m->msg_flags & MSG_CTRUNC) &&
423 CMSG_NXTHDR (m, cm) == NULL &&
424 ((char *) payload + payload_len_bytes >
425 (char *) m->msg_control + m->msg_controllen))
426 {
427 /* This is the last cmsg in a truncated message and using
428 * cmsg_len would apparently overrun the allocated buffer.
429 * Some operating systems (illumos and Solaris are known) do
430 * not adjust cmsg_len in the last cmsg when truncation occurs.
431 * Adjust the payload length here. The calculation for
432 * payload_len_fds below will discard any trailing bytes that
433 * belong to an incomplete file descriptor - the kernel will
434 * have already closed that (at least for illumos and Solaris)
435 */
436 payload_len_bytes = m->msg_controllen -
437 ((char *) payload - (char *) m->msg_control);
438 }
439
440 payload_len_fds = payload_len_bytes / sizeof (int);
441
442 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
443 {
444 /* The fds in the payload will fit in our buffer */
445 fds_to_use = payload_len_fds;
446 }
447 else
448 {
449 /* Too many fds in the payload.
450 * When called from _dbus_read_socket_with_unix_fds(),
451 * this shouldn't happen any more because we're setting
452 * m.msg_controllen to the exact number we can accept,
453 * but be safe and truncate. */
454 fds_to_use = (size_t) *n_fds;
455
456 /* Close the excess fds to avoid DoS: if they stayed open,
457 * someone could send us an extra fd per message
458 * and we'd eventually run out. */
459 for (i = fds_to_use; i < payload_len_fds; i++)
460 {
461 close (payload[i]);
462 }
463 }
464
465 if (fds_to_use != 0)
466 memcpy (fds, payload, fds_to_use * sizeof (int));
467
468 found = TRUE;
469 /* This narrowing cast from size_t to unsigned int cannot
470 * overflow because we have chosen fds_to_use
471 * to be <= *n_fds */
472 *n_fds = (unsigned int) fds_to_use;
473
474 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
475 worked, hence we need to go through this list and set
476 CLOEXEC everywhere in any case */
477 for (i = 0; i < fds_to_use; i++)
479
480 break;
481 }
482 }
483
484 if (!found)
485 *n_fds = 0;
486
487 if (m->msg_flags & MSG_CTRUNC)
488 {
489 unsigned int i;
490
491 /* Hmm, apparently the control data was truncated. The bad
492 thing is that we might have completely lost a couple of fds
493 without chance to recover them. Hence let's treat this as a
494 serious error. */
495
496 /* We still need to close whatever fds we *did* receive,
497 * otherwise they'll never get closed. (CVE-2020-12049) */
498 for (i = 0; i < *n_fds; i++)
499 close (fds[i]);
500
501 *n_fds = 0;
502 errno = ENOSPC;
503 return FALSE;
504 }
505
506 return TRUE;
507}
508#endif
509
522int
524 DBusString *buffer,
525 int count,
526 int *fds,
527 unsigned int *n_fds) {
528#ifndef HAVE_UNIX_FD_PASSING
529 int r;
530
531 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
532 return r;
533
534 *n_fds = 0;
535 return r;
536
537#else
538 int bytes_read;
539 int start;
540 struct msghdr m;
541 struct iovec iov;
542
543 _dbus_assert (count >= 0);
545
546 start = _dbus_string_get_length (buffer);
547
548 if (!_dbus_string_lengthen (buffer, count))
549 {
550 errno = ENOMEM;
551 return -1;
552 }
553
554 _DBUS_ZERO(iov);
555 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
556 iov.iov_len = count;
557
558 _DBUS_ZERO(m);
559 m.msg_iov = &iov;
560 m.msg_iovlen = 1;
561
562 /* Hmm, we have no clue how long the control data will actually be
563 that is queued for us. The least we can do is assume that the
564 caller knows. Hence let's make space for the number of fds that
565 we shall read at max plus the cmsg header. */
566 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
567
568 /* It's probably safe to assume that systems with SCM_RIGHTS also
569 know alloca() */
570 m.msg_control = alloca(m.msg_controllen);
571 memset(m.msg_control, 0, m.msg_controllen);
572
573 /* Do not include the padding at the end when we tell the kernel
574 * how much we're willing to receive. This avoids getting
575 * the padding filled with additional fds that we weren't expecting,
576 * if a (potentially malicious) sender included them. (fd.o #83622) */
577 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
578
579 again:
580
581 bytes_read = recvmsg (fd.fd, &m, 0
582#ifdef MSG_CMSG_CLOEXEC
583 |MSG_CMSG_CLOEXEC
584#endif
585 );
586
587 if (bytes_read < 0)
588 {
589 if (errno == EINTR)
590 goto again;
591 else
592 {
593 /* put length back (note that this doesn't actually realloc anything) */
594 _dbus_string_set_length (buffer, start);
595 return -1;
596 }
597 }
598 else
599 {
600 if (!_dbus_socket_unpack_or_close_scm_rights (&m, fds, n_fds))
601 {
602 _dbus_string_set_length (buffer, start);
603 return -1;
604 }
605
606 /* put length back (doesn't actually realloc) */
607 _dbus_string_set_length (buffer, start + bytes_read);
608
609#if 0
610 if (bytes_read > 0)
611 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
612#endif
613
614 return bytes_read;
615 }
616#endif
617}
618
619int
620_dbus_write_socket_with_unix_fds(DBusSocket fd,
621 const DBusString *buffer,
622 int start,
623 int len,
624 const int *fds,
625 int n_fds) {
626
627#ifndef HAVE_UNIX_FD_PASSING
628
629 if (n_fds > 0) {
630 errno = ENOTSUP;
631 return -1;
632 }
633
634 return _dbus_write_socket(fd, buffer, start, len);
635#else
636 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
637#endif
638}
639
640int
641_dbus_write_socket_with_unix_fds_two(DBusSocket fd,
642 const DBusString *buffer1,
643 int start1,
644 int len1,
645 const DBusString *buffer2,
646 int start2,
647 int len2,
648 const int *fds,
649 int n_fds) {
650
651#ifndef HAVE_UNIX_FD_PASSING
652
653 if (n_fds > 0) {
654 errno = ENOTSUP;
655 return -1;
656 }
657
658 return _dbus_write_socket_two(fd,
659 buffer1, start1, len1,
660 buffer2, start2, len2);
661#else
662
663 struct msghdr m;
664 struct cmsghdr *cm;
665 struct iovec iov[2];
666 int bytes_written;
667
668 _dbus_assert (len1 >= 0);
669 _dbus_assert (len2 >= 0);
670 _dbus_assert (n_fds >= 0);
671
672 _DBUS_ZERO(iov);
673 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
674 iov[0].iov_len = len1;
675
676 if (buffer2)
677 {
678 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
679 iov[1].iov_len = len2;
680 }
681
682 _DBUS_ZERO(m);
683 m.msg_iov = iov;
684 m.msg_iovlen = buffer2 ? 2 : 1;
685
686 if (n_fds > 0)
687 {
688 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
689 m.msg_control = alloca(m.msg_controllen);
690 memset(m.msg_control, 0, m.msg_controllen);
691
692 cm = CMSG_FIRSTHDR(&m);
693 cm->cmsg_level = SOL_SOCKET;
694 cm->cmsg_type = SCM_RIGHTS;
695 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
696 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
697 }
698
699 again:
700
701 bytes_written = sendmsg (fd.fd, &m, 0
702#if HAVE_DECL_MSG_NOSIGNAL
703 |MSG_NOSIGNAL
704#endif
705 );
706
707 if (bytes_written < 0 && errno == EINTR)
708 goto again;
709
710#if 0
711 if (bytes_written > 0)
712 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
713#endif
714
715 return bytes_written;
716#endif
717}
718
732int
734 const DBusString *buffer1,
735 int start1,
736 int len1,
737 const DBusString *buffer2,
738 int start2,
739 int len2)
740{
741#if HAVE_DECL_MSG_NOSIGNAL
742 struct iovec vectors[2];
743 const char *data1;
744 const char *data2;
745 int bytes_written;
746 struct msghdr m;
747
748 _dbus_assert (buffer1 != NULL);
749 _dbus_assert (start1 >= 0);
750 _dbus_assert (start2 >= 0);
751 _dbus_assert (len1 >= 0);
752 _dbus_assert (len2 >= 0);
753
754 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
755
756 if (buffer2 != NULL)
757 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
758 else
759 {
760 data2 = NULL;
761 start2 = 0;
762 len2 = 0;
763 }
764
765 vectors[0].iov_base = (char*) data1;
766 vectors[0].iov_len = len1;
767 vectors[1].iov_base = (char*) data2;
768 vectors[1].iov_len = len2;
769
770 _DBUS_ZERO(m);
771 m.msg_iov = vectors;
772 m.msg_iovlen = data2 ? 2 : 1;
773
774 again:
775
776 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
777
778 if (bytes_written < 0 && errno == EINTR)
779 goto again;
780
781 return bytes_written;
782
783#else
784 return _dbus_write_two (fd.fd, buffer1, start1, len1,
785 buffer2, start2, len2);
786#endif
787}
788
805int
807 DBusString *buffer,
808 int count)
809{
810 int bytes_read;
811 int start;
812 char *data;
813
814 _dbus_assert (count >= 0);
815
816 start = _dbus_string_get_length (buffer);
817
818 if (!_dbus_string_lengthen (buffer, count))
819 {
820 errno = ENOMEM;
821 return -1;
822 }
823
824 data = _dbus_string_get_data_len (buffer, start, count);
825
826 again:
827
828 bytes_read = read (fd, data, count);
829
830 if (bytes_read < 0)
831 {
832 if (errno == EINTR)
833 goto again;
834 else
835 {
836 /* put length back (note that this doesn't actually realloc anything) */
837 _dbus_string_set_length (buffer, start);
838 return -1;
839 }
840 }
841 else
842 {
843 /* put length back (doesn't actually realloc) */
844 _dbus_string_set_length (buffer, start + bytes_read);
845
846#if 0
847 if (bytes_read > 0)
848 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
849#endif
850
851 return bytes_read;
852 }
853}
854
865int
867 const DBusString *buffer,
868 int start,
869 int len)
870{
871 const char *data;
872 int bytes_written;
873
874 data = _dbus_string_get_const_data_len (buffer, start, len);
875
876 again:
877
878 bytes_written = write (fd, data, len);
879
880 if (bytes_written < 0 && errno == EINTR)
881 goto again;
882
883#if 0
884 if (bytes_written > 0)
885 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
886#endif
887
888 return bytes_written;
889}
890
911int
913 const DBusString *buffer1,
914 int start1,
915 int len1,
916 const DBusString *buffer2,
917 int start2,
918 int len2)
919{
920 _dbus_assert (buffer1 != NULL);
921 _dbus_assert (start1 >= 0);
922 _dbus_assert (start2 >= 0);
923 _dbus_assert (len1 >= 0);
924 _dbus_assert (len2 >= 0);
925
926#ifdef HAVE_WRITEV
927 {
928 struct iovec vectors[2];
929 const char *data1;
930 const char *data2;
931 int bytes_written;
932
933 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
934
935 if (buffer2 != NULL)
936 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
937 else
938 {
939 data2 = NULL;
940 start2 = 0;
941 len2 = 0;
942 }
943
944 vectors[0].iov_base = (char*) data1;
945 vectors[0].iov_len = len1;
946 vectors[1].iov_base = (char*) data2;
947 vectors[1].iov_len = len2;
948
949 again:
950
951 bytes_written = writev (fd,
952 vectors,
953 data2 ? 2 : 1);
954
955 if (bytes_written < 0 && errno == EINTR)
956 goto again;
957
958 return bytes_written;
959 }
960#else /* HAVE_WRITEV */
961 {
962 int ret1, ret2;
963
964 ret1 = _dbus_write (fd, buffer1, start1, len1);
965 if (ret1 == len1 && buffer2 != NULL)
966 {
967 ret2 = _dbus_write (fd, buffer2, start2, len2);
968 if (ret2 < 0)
969 ret2 = 0; /* we can't report an error as the first write was OK */
970
971 return ret1 + ret2;
972 }
973 else
974 return ret1;
975 }
976#endif /* !HAVE_WRITEV */
977}
978
997 dbus_bool_t abstract,
998 DBusError *error)
999{
1000 DBusSocket fd = DBUS_SOCKET_INIT;
1001 size_t path_len;
1002 struct sockaddr_un addr;
1003 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1004
1005 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1006
1007 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
1008 path, abstract);
1009
1010
1011 if (!_dbus_open_unix_socket (&fd.fd, error))
1012 {
1013 _DBUS_ASSERT_ERROR_IS_SET(error);
1014 return fd;
1015 }
1016 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1017
1018 _DBUS_ZERO (addr);
1019 addr.sun_family = AF_UNIX;
1020 path_len = strlen (path);
1021
1022 if (abstract)
1023 {
1024#ifdef __linux__
1025 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1026 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1027
1028 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1029 {
1031 "Abstract socket name too long\n");
1032 _dbus_close_socket (&fd, NULL);
1033 return fd;
1034 }
1035
1036 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1037 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1038#else /* !__linux__ */
1040 "Operating system does not support abstract socket namespace\n");
1041 _dbus_close_socket (&fd, NULL);
1042 return fd;
1043#endif /* !__linux__ */
1044 }
1045 else
1046 {
1047 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1048 {
1050 "Socket name too long\n");
1051 _dbus_close_socket (&fd, NULL);
1052 return fd;
1053 }
1054
1055 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1056 }
1057
1058 if (connect (fd.fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1059 {
1060 dbus_set_error (error,
1061 _dbus_error_from_errno (errno),
1062 "Failed to connect to socket %s: %s",
1063 path, _dbus_strerror (errno));
1064
1065 _dbus_close_socket (&fd, NULL);
1066 return fd;
1067 }
1068
1069 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1070 {
1071 _DBUS_ASSERT_ERROR_IS_SET (error);
1072
1073 _dbus_close_socket (&fd, NULL);
1074 return fd;
1075 }
1076
1077 return fd;
1078}
1079
1093_dbus_connect_exec (const char *path,
1094 char *const argv[],
1095 DBusError *error)
1096{
1097 DBusSocket s = DBUS_SOCKET_INIT;
1098 int fds[2];
1099 pid_t pid;
1100 int retval;
1101 dbus_bool_t cloexec_done = 0;
1102
1103 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1104
1105 _dbus_verbose ("connecting to process %s\n", path);
1106
1107#ifdef SOCK_CLOEXEC
1108 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1109 cloexec_done = (retval >= 0);
1110
1111 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1112#endif
1113 {
1114 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1115 }
1116
1117 if (retval < 0)
1118 {
1119 dbus_set_error (error,
1120 _dbus_error_from_errno (errno),
1121 "Failed to create socket pair: %s",
1122 _dbus_strerror (errno));
1123 _dbus_assert (!_dbus_socket_is_valid (s));
1124 return s;
1125 }
1126
1127 if (!cloexec_done)
1128 {
1131 }
1132
1133 /* Make sure our output buffers aren't redundantly printed by both the
1134 * parent and the child */
1135 fflush (stdout);
1136 fflush (stderr);
1137
1138 pid = fork ();
1139 if (pid < 0)
1140 {
1141 dbus_set_error (error,
1142 _dbus_error_from_errno (errno),
1143 "Failed to fork() to call %s: %s",
1144 path, _dbus_strerror (errno));
1145 close (fds[0]);
1146 close (fds[1]);
1147 _dbus_assert (!_dbus_socket_is_valid (s));
1148 return s;
1149 }
1150
1151 if (pid == 0)
1152 {
1153 /* child */
1154 close (fds[0]);
1155
1156 dup2 (fds[1], STDIN_FILENO);
1157 dup2 (fds[1], STDOUT_FILENO);
1158
1159 if (fds[1] != STDIN_FILENO &&
1160 fds[1] != STDOUT_FILENO)
1161 close (fds[1]);
1162
1163 /* Inherit STDERR and the controlling terminal from the
1164 parent */
1165
1166 _dbus_close_all ();
1167
1168 execvp (path, (char * const *) argv);
1169
1170 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1171
1172 _exit(1);
1173 }
1174
1175 /* parent */
1176 close (fds[1]);
1177
1178 if (!_dbus_set_fd_nonblocking (fds[0], error))
1179 {
1180 _DBUS_ASSERT_ERROR_IS_SET (error);
1181
1182 close (fds[0]);
1183 _dbus_assert (!_dbus_socket_is_valid (s));
1184 return s;
1185 }
1186
1187 s.fd = fds[0];
1188 return s;
1189}
1190
1210 dbus_bool_t abstract,
1211 DBusError *error)
1212{
1213 DBusSocket s = DBUS_SOCKET_INIT;
1214 int listen_fd;
1215 struct sockaddr_un addr;
1216 size_t path_len;
1217 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1218
1219 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1220
1221 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1222 path, abstract);
1223
1224 if (!_dbus_open_unix_socket (&listen_fd, error))
1225 {
1226 _DBUS_ASSERT_ERROR_IS_SET(error);
1227 return s;
1228 }
1229 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1230
1231 _DBUS_ZERO (addr);
1232 addr.sun_family = AF_UNIX;
1233 path_len = strlen (path);
1234
1235 if (abstract)
1236 {
1237#ifdef __linux__
1238 /* remember that abstract names aren't nul-terminated so we rely
1239 * on sun_path being filled in with zeroes above.
1240 */
1241 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1242 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1243
1244 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1245 {
1247 "Abstract socket name too long\n");
1248 _dbus_close (listen_fd, NULL);
1249 return s;
1250 }
1251
1252 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1253 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1254#else /* !__linux__ */
1256 "Operating system does not support abstract socket namespace\n");
1257 _dbus_close (listen_fd, NULL);
1258 return s;
1259#endif /* !__linux__ */
1260 }
1261 else
1262 {
1263 /* Discussed security implications of this with Nalin,
1264 * and we couldn't think of where it would kick our ass, but
1265 * it still seems a bit sucky. It also has non-security suckage;
1266 * really we'd prefer to exit if the socket is already in use.
1267 * But there doesn't seem to be a good way to do this.
1268 *
1269 * Just to be extra careful, I threw in the stat() - clearly
1270 * the stat() can't *fix* any security issue, but it at least
1271 * avoids inadvertent/accidental data loss.
1272 */
1273 {
1274 struct stat sb;
1275
1276 if (stat (path, &sb) == 0 &&
1277 S_ISSOCK (sb.st_mode))
1278 unlink (path);
1279 }
1280
1281 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1282 {
1284 "Socket name too long\n");
1285 _dbus_close (listen_fd, NULL);
1286 return s;
1287 }
1288
1289 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1290 }
1291
1292 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1293 {
1294 dbus_set_error (error, _dbus_error_from_errno (errno),
1295 "Failed to bind socket \"%s\": %s",
1296 path, _dbus_strerror (errno));
1297 _dbus_close (listen_fd, NULL);
1298 return s;
1299 }
1300
1301 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1302 {
1303 dbus_set_error (error, _dbus_error_from_errno (errno),
1304 "Failed to listen on socket \"%s\": %s",
1305 path, _dbus_strerror (errno));
1306 _dbus_close (listen_fd, NULL);
1307 return s;
1308 }
1309
1310 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1311 {
1312 _DBUS_ASSERT_ERROR_IS_SET (error);
1313 _dbus_close (listen_fd, NULL);
1314 return s;
1315 }
1316
1317 /* Try opening up the permissions, but if we can't, just go ahead
1318 * and continue, maybe it will be good enough.
1319 */
1320 if (!abstract && chmod (path, 0777) < 0)
1321 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1322
1323 s.fd = listen_fd;
1324 return s;
1325}
1326
1337int
1339 DBusError *error)
1340{
1341#ifdef HAVE_SYSTEMD
1342 int r, n;
1343 int fd;
1344 DBusSocket *new_fds;
1345
1346 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1347
1348 n = sd_listen_fds (TRUE);
1349 if (n < 0)
1350 {
1352 "Failed to acquire systemd socket: %s",
1353 _dbus_strerror (-n));
1354 return -1;
1355 }
1356
1357 if (n <= 0)
1358 {
1360 "No socket received.");
1361 return -1;
1362 }
1363
1364 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1365 {
1366 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1367 if (r < 0)
1368 {
1370 "Failed to verify systemd socket type: %s",
1371 _dbus_strerror (-r));
1372 return -1;
1373 }
1374
1375 if (!r)
1376 {
1378 "Passed socket has wrong type.");
1379 return -1;
1380 }
1381 }
1382
1383 /* OK, the file descriptors are all good, so let's take posession of
1384 them then. */
1385
1386 new_fds = dbus_new (DBusSocket, n);
1387 if (!new_fds)
1388 {
1390 "Failed to allocate file handle array.");
1391 goto fail;
1392 }
1393
1394 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1395 {
1396 if (!_dbus_set_fd_nonblocking (fd, error))
1397 {
1398 _DBUS_ASSERT_ERROR_IS_SET (error);
1399 goto fail;
1400 }
1401
1402 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1403 }
1404
1405 *fds = new_fds;
1406 return n;
1407
1408 fail:
1409
1410 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1411 {
1412 _dbus_close (fd, NULL);
1413 }
1414
1415 dbus_free (new_fds);
1416 return -1;
1417#else
1419 "dbus was compiled without systemd support");
1420 return -1;
1421#endif
1422}
1423
1424/* Convert an error code from getaddrinfo() or getnameinfo() into
1425 * a D-Bus error name. */
1426static const char *
1427_dbus_error_from_gai (int gai_res,
1428 int saved_errno)
1429{
1430 switch (gai_res)
1431 {
1432#ifdef EAI_FAMILY
1433 case EAI_FAMILY:
1434 /* ai_family not supported (at all) */
1436#endif
1437
1438#ifdef EAI_SOCKTYPE
1439 case EAI_SOCKTYPE:
1440 /* ai_socktype not supported (at all) */
1442#endif
1443
1444#ifdef EAI_MEMORY
1445 case EAI_MEMORY:
1446 /* Out of memory */
1447 return DBUS_ERROR_NO_MEMORY;
1448#endif
1449
1450#ifdef EAI_SYSTEM
1451 case EAI_SYSTEM:
1452 /* Unspecified system error, details in errno */
1453 return _dbus_error_from_errno (saved_errno);
1454#endif
1455
1456 case 0:
1457 /* It succeeded, but we didn't get any addresses? */
1458 return DBUS_ERROR_FAILED;
1459
1460 /* EAI_AGAIN: Transient failure */
1461 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1462 /* EAI_FAIL: Non-recoverable failure */
1463 /* EAI_NODATA: host exists but has no addresses */
1464 /* EAI_NONAME: host does not exist */
1465 /* EAI_OVERFLOW: argument buffer overflow */
1466 /* EAI_SERVICE: service not available for specified socket
1467 * type (we should never see this because we use numeric
1468 * ports) */
1469 default:
1470 return DBUS_ERROR_FAILED;
1471 }
1472}
1473
1489 const char *port,
1490 const char *family,
1491 DBusError *error)
1492{
1493 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1494}
1495
1497_dbus_connect_tcp_socket_with_nonce (const char *host,
1498 const char *port,
1499 const char *family,
1500 const char *noncefile,
1501 DBusError *error)
1502{
1503 int saved_errno = 0;
1504 DBusList *connect_errors = NULL;
1505 DBusSocket fd = DBUS_SOCKET_INIT;
1506 int res;
1507 struct addrinfo hints;
1508 struct addrinfo *ai = NULL;
1509 const struct addrinfo *tmp;
1510 DBusError *connect_error;
1511
1512 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1513
1514 _DBUS_ZERO (hints);
1515
1516 if (!family)
1517 hints.ai_family = AF_UNSPEC;
1518 else if (!strcmp(family, "ipv4"))
1519 hints.ai_family = AF_INET;
1520 else if (!strcmp(family, "ipv6"))
1521 hints.ai_family = AF_INET6;
1522 else
1523 {
1524 dbus_set_error (error,
1526 "Unknown address family %s", family);
1527 return _dbus_socket_get_invalid ();
1528 }
1529 hints.ai_protocol = IPPROTO_TCP;
1530 hints.ai_socktype = SOCK_STREAM;
1531 hints.ai_flags = AI_ADDRCONFIG;
1532
1533 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1534 {
1535 dbus_set_error (error,
1536 _dbus_error_from_gai (res, errno),
1537 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1538 host, port, gai_strerror(res), res);
1539 goto out;
1540 }
1541
1542 tmp = ai;
1543 while (tmp)
1544 {
1545 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1546 {
1547 _DBUS_ASSERT_ERROR_IS_SET(error);
1548 _dbus_socket_invalidate (&fd);
1549 goto out;
1550 }
1551 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1552
1553 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1554 {
1555 saved_errno = errno;
1556 _dbus_close_socket (&fd, NULL);
1557
1558 connect_error = dbus_new0 (DBusError, 1);
1559
1560 if (connect_error == NULL)
1561 {
1562 _DBUS_SET_OOM (error);
1563 goto out;
1564 }
1565
1566 dbus_error_init (connect_error);
1567 _dbus_set_error_with_inet_sockaddr (connect_error,
1568 tmp->ai_addr, tmp->ai_addrlen,
1569 "Failed to connect to socket",
1570 saved_errno);
1571
1572 if (!_dbus_list_append (&connect_errors, connect_error))
1573 {
1574 dbus_error_free (connect_error);
1575 dbus_free (connect_error);
1576 _DBUS_SET_OOM (error);
1577 goto out;
1578 }
1579
1580 tmp = tmp->ai_next;
1581 continue;
1582 }
1583
1584 break;
1585 }
1586
1587 if (!_dbus_socket_is_valid (fd))
1588 {
1589 _dbus_combine_tcp_errors (&connect_errors, "Failed to connect",
1590 host, port, error);
1591 goto out;
1592 }
1593
1594 if (noncefile != NULL)
1595 {
1596 DBusString noncefileStr;
1597 dbus_bool_t ret;
1598 _dbus_string_init_const (&noncefileStr, noncefile);
1599 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1600
1601 if (!ret)
1602 {
1603 _dbus_close_socket (&fd, NULL);
1604 goto out;
1605 }
1606 }
1607
1608 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1609 {
1610 _dbus_close_socket (&fd, NULL);
1611 goto out;
1612 }
1613
1614out:
1615 if (ai != NULL)
1616 freeaddrinfo (ai);
1617
1618 while ((connect_error = _dbus_list_pop_first (&connect_errors)))
1619 {
1620 dbus_error_free (connect_error);
1621 dbus_free (connect_error);
1622 }
1623
1624 return fd;
1625}
1626
1644int
1645_dbus_listen_tcp_socket (const char *host,
1646 const char *port,
1647 const char *family,
1648 DBusString *retport,
1649 const char **retfamily,
1650 DBusSocket **fds_p,
1651 DBusError *error)
1652{
1653 int saved_errno;
1654 int nlisten_fd = 0, res, i;
1655 DBusList *bind_errors = NULL;
1656 DBusError *bind_error = NULL;
1657 DBusSocket *listen_fd = NULL;
1658 struct addrinfo hints;
1659 struct addrinfo *ai, *tmp;
1660 unsigned int reuseaddr;
1661 dbus_bool_t have_ipv4 = FALSE;
1662 dbus_bool_t have_ipv6 = FALSE;
1663
1664 *fds_p = NULL;
1665 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1666
1667 _DBUS_ZERO (hints);
1668
1669 if (!family)
1670 hints.ai_family = AF_UNSPEC;
1671 else if (!strcmp(family, "ipv4"))
1672 hints.ai_family = AF_INET;
1673 else if (!strcmp(family, "ipv6"))
1674 hints.ai_family = AF_INET6;
1675 else
1676 {
1677 dbus_set_error (error,
1679 "Unknown address family %s", family);
1680 return -1;
1681 }
1682
1683 hints.ai_protocol = IPPROTO_TCP;
1684 hints.ai_socktype = SOCK_STREAM;
1685 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1686
1687 redo_lookup_with_port:
1688 ai = NULL;
1689 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1690 {
1691 dbus_set_error (error,
1692 _dbus_error_from_gai (res, errno),
1693 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1694 host ? host : "*", port ? port : "0", gai_strerror(res), res);
1695 goto failed;
1696 }
1697
1698 tmp = ai;
1699 while (tmp)
1700 {
1701 int fd = -1, tcp_nodelay_on;
1702 DBusSocket *newlisten_fd;
1703
1704 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1705 {
1706 _DBUS_ASSERT_ERROR_IS_SET(error);
1707 goto failed;
1708 }
1709 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1710
1711 reuseaddr = 1;
1712 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1713 {
1714 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1715 host ? host : "*", port ? port : "0", _dbus_strerror (errno));
1716 }
1717
1718 /* Nagle's algorithm imposes a huge delay on the initial messages
1719 going over TCP. */
1720 tcp_nodelay_on = 1;
1721 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1722 {
1723 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1724 host ? host : "*", port ? port : "0", _dbus_strerror (errno));
1725 }
1726
1727 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1728 {
1729 saved_errno = errno;
1730 _dbus_close(fd, NULL);
1731
1732 /*
1733 * We don't treat this as a fatal error, because there might be
1734 * other addresses that we can listen on. In particular:
1735 *
1736 * - If saved_errno is EADDRINUSE after we
1737 * "goto redo_lookup_with_port" after binding a port on one of the
1738 * possible addresses, we will try to bind that same port on
1739 * every address, including the same address again for a second
1740 * time, which will fail with EADDRINUSE.
1741 *
1742 * - If saved_errno is EADDRINUSE, it might be because binding to
1743 * an IPv6 address implicitly binds to a corresponding IPv4
1744 * address or vice versa (e.g. Linux with bindv6only=0).
1745 *
1746 * - If saved_errno is EADDRNOTAVAIL when we asked for family
1747 * AF_UNSPEC, it might be because IPv6 is disabled for this
1748 * particular interface (e.g. Linux with
1749 * /proc/sys/net/ipv6/conf/lo/disable_ipv6).
1750 */
1751 bind_error = dbus_new0 (DBusError, 1);
1752
1753 if (bind_error == NULL)
1754 {
1755 _DBUS_SET_OOM (error);
1756 goto failed;
1757 }
1758
1759 dbus_error_init (bind_error);
1760 _dbus_set_error_with_inet_sockaddr (bind_error, tmp->ai_addr, tmp->ai_addrlen,
1761 "Failed to bind socket",
1762 saved_errno);
1763
1764 if (!_dbus_list_append (&bind_errors, bind_error))
1765 {
1766 dbus_error_free (bind_error);
1767 dbus_free (bind_error);
1768 _DBUS_SET_OOM (error);
1769 goto failed;
1770 }
1771
1772 /* Try the next address, maybe it will work better */
1773 tmp = tmp->ai_next;
1774 continue;
1775 }
1776
1777 if (listen (fd, 30 /* backlog */) < 0)
1778 {
1779 saved_errno = errno;
1780 _dbus_close (fd, NULL);
1781 _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen,
1782 "Failed to listen on socket",
1783 saved_errno);
1784 goto failed;
1785 }
1786
1787 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1788 if (!newlisten_fd)
1789 {
1790 _dbus_close (fd, NULL);
1792 "Failed to allocate file handle array");
1793 goto failed;
1794 }
1795 listen_fd = newlisten_fd;
1796 listen_fd[nlisten_fd].fd = fd;
1797 nlisten_fd++;
1798
1799 if (tmp->ai_addr->sa_family == AF_INET)
1800 have_ipv4 = TRUE;
1801 else if (tmp->ai_addr->sa_family == AF_INET6)
1802 have_ipv6 = TRUE;
1803
1804 if (!_dbus_string_get_length(retport))
1805 {
1806 /* If the user didn't specify a port, or used 0, then
1807 the kernel chooses a port. After the first address
1808 is bound to, we need to force all remaining addresses
1809 to use the same port */
1810 if (!port || !strcmp(port, "0"))
1811 {
1812 int result;
1813 struct sockaddr_storage addr;
1814 socklen_t addrlen;
1815 char portbuf[50];
1816
1817 addrlen = sizeof(addr);
1818 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1819
1820 if (result == -1)
1821 {
1822 saved_errno = errno;
1823 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1824 "Failed to retrieve socket name for \"%s:%s\": %s",
1825 host ? host : "*", port ? port : "0", _dbus_strerror (saved_errno));
1826 goto failed;
1827 }
1828
1829 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1830 portbuf, sizeof(portbuf),
1831 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1832 {
1833 saved_errno = errno;
1834 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1835 "Failed to resolve port \"%s:%s\": %s (%d)",
1836 host ? host : "*", port ? port : "0", gai_strerror(res), res);
1837 goto failed;
1838 }
1839
1840 if (!_dbus_string_append(retport, portbuf))
1841 {
1843 goto failed;
1844 }
1845
1846 /* Release current address list & redo lookup */
1847 port = _dbus_string_get_const_data(retport);
1848 freeaddrinfo(ai);
1849 goto redo_lookup_with_port;
1850 }
1851 else
1852 {
1853 if (!_dbus_string_append(retport, port))
1854 {
1856 goto failed;
1857 }
1858 }
1859 }
1860
1861 tmp = tmp->ai_next;
1862 }
1863 freeaddrinfo(ai);
1864 ai = NULL;
1865
1866 if (!nlisten_fd)
1867 {
1868 _dbus_combine_tcp_errors (&bind_errors, "Failed to bind", host,
1869 port, error);
1870 goto failed;
1871 }
1872
1873 if (have_ipv4 && !have_ipv6)
1874 *retfamily = "ipv4";
1875 else if (!have_ipv4 && have_ipv6)
1876 *retfamily = "ipv6";
1877
1878 for (i = 0 ; i < nlisten_fd ; i++)
1879 {
1880 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1881 {
1882 goto failed;
1883 }
1884 }
1885
1886 *fds_p = listen_fd;
1887
1888 /* This list might be non-empty even on success, because we might be
1889 * ignoring EADDRINUSE or EADDRNOTAVAIL */
1890 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1891 {
1892 dbus_error_free (bind_error);
1893 dbus_free (bind_error);
1894 }
1895
1896 return nlisten_fd;
1897
1898 failed:
1899 if (ai)
1900 freeaddrinfo(ai);
1901 for (i = 0 ; i < nlisten_fd ; i++)
1902 _dbus_close(listen_fd[i].fd, NULL);
1903
1904 while ((bind_error = _dbus_list_pop_first (&bind_errors)))
1905 {
1906 dbus_error_free (bind_error);
1907 dbus_free (bind_error);
1908 }
1909
1910 dbus_free(listen_fd);
1911 return -1;
1912}
1913
1914static dbus_bool_t
1915write_credentials_byte (int server_fd,
1916 DBusError *error)
1917{
1918 int bytes_written;
1919 char buf[1] = { '\0' };
1920#if defined(HAVE_CMSGCRED)
1921 union {
1922 struct cmsghdr hdr;
1923 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1924 } cmsg;
1925 struct iovec iov;
1926 struct msghdr msg;
1927 iov.iov_base = buf;
1928 iov.iov_len = 1;
1929
1930 _DBUS_ZERO(msg);
1931 msg.msg_iov = &iov;
1932 msg.msg_iovlen = 1;
1933
1934 msg.msg_control = (caddr_t) &cmsg;
1935 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1936 _DBUS_ZERO(cmsg);
1937 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1938 cmsg.hdr.cmsg_level = SOL_SOCKET;
1939 cmsg.hdr.cmsg_type = SCM_CREDS;
1940#endif
1941
1942 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1943
1944 again:
1945
1946#if defined(HAVE_CMSGCRED)
1947 bytes_written = sendmsg (server_fd, &msg, 0
1948#if HAVE_DECL_MSG_NOSIGNAL
1949 |MSG_NOSIGNAL
1950#endif
1951 );
1952
1953 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1954 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1955 * only allows that on AF_UNIX. Try just doing a send() instead. */
1956 if (bytes_written < 0 && errno == EINVAL)
1957#endif
1958 {
1959 bytes_written = send (server_fd, buf, 1, 0
1960#if HAVE_DECL_MSG_NOSIGNAL
1961 |MSG_NOSIGNAL
1962#endif
1963 );
1964 }
1965
1966 if (bytes_written < 0 && errno == EINTR)
1967 goto again;
1968
1969 if (bytes_written < 0)
1970 {
1971 dbus_set_error (error, _dbus_error_from_errno (errno),
1972 "Failed to write credentials byte: %s",
1973 _dbus_strerror (errno));
1974 return FALSE;
1975 }
1976 else if (bytes_written == 0)
1977 {
1979 "wrote zero bytes writing credentials byte");
1980 return FALSE;
1981 }
1982 else
1983 {
1984 _dbus_assert (bytes_written == 1);
1985 _dbus_verbose ("wrote credentials byte\n");
1986 return TRUE;
1987 }
1988}
1989
1990/* return FALSE on OOM, TRUE otherwise, even if no groups were found */
1991static dbus_bool_t
1992add_groups_to_credentials (int client_fd,
1993 DBusCredentials *credentials,
1994 dbus_gid_t primary)
1995{
1996#if defined(__linux__) && defined(SO_PEERGROUPS)
1997 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1998 /* This function assumes socklen_t is unsigned, which is true on Linux */
1999 _DBUS_STATIC_ASSERT (((socklen_t) -1) > 0);
2000 gid_t *buf = NULL;
2001 socklen_t len = 1024;
2002 dbus_bool_t oom = FALSE;
2003 /* libdbus has a different representation of group IDs just to annoy you */
2004 dbus_gid_t *converted_gids = NULL;
2005 dbus_bool_t need_primary = TRUE;
2006 size_t n_gids;
2007 size_t i;
2008
2009 n_gids = ((size_t) len) / sizeof (gid_t);
2010 buf = dbus_new (gid_t, n_gids);
2011
2012 if (buf == NULL)
2013 return FALSE;
2014
2015 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERGROUPS, buf, &len) < 0)
2016 {
2017 int e = errno;
2018 gid_t *replacement;
2019
2020 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
2021 _dbus_strerror (e), (unsigned long) len);
2022
2023 if (e != ERANGE || (size_t) len <= n_gids * sizeof (gid_t))
2024 {
2025 _dbus_verbose ("Failed to getsockopt(SO_PEERGROUPS): %s\n",
2026 _dbus_strerror (e));
2027 goto out;
2028 }
2029
2030 /* If not enough space, len is updated to be enough.
2031 * Try again with a large enough buffer. */
2032 n_gids = ((size_t) len) / sizeof (gid_t);
2033 replacement = dbus_realloc (buf, len);
2034
2035 if (replacement == NULL)
2036 {
2037 oom = TRUE;
2038 goto out;
2039 }
2040
2041 buf = replacement;
2042 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
2043 }
2044
2045 if (len > n_gids * sizeof (gid_t))
2046 {
2047 _dbus_verbose ("%lu > %zu", (unsigned long) len, n_gids * sizeof (gid_t));
2048 _dbus_assert_not_reached ("getsockopt(SO_PEERGROUPS) overflowed");
2049 }
2050
2051 if (len % sizeof (gid_t) != 0)
2052 {
2053 _dbus_verbose ("getsockopt(SO_PEERGROUPS) did not return an "
2054 "integer multiple of sizeof(gid_t): %lu should be "
2055 "divisible by %zu",
2056 (unsigned long) len, sizeof (gid_t));
2057 goto out;
2058 }
2059
2060 /* Allocate an extra space for the primary group ID */
2061 n_gids = ((size_t) len) / sizeof (gid_t);
2062
2063 /* If n_gids is less than this, then (n_gids + 1) certainly doesn't
2064 * overflow, and neither does multiplying that by sizeof(dbus_gid_t).
2065 * This is using _DBUS_INT32_MAX as a conservative lower bound for
2066 * the maximum size_t. */
2067 if (n_gids >= (_DBUS_INT32_MAX / sizeof (dbus_gid_t)) - 1)
2068 {
2069 _dbus_verbose ("getsockopt(SO_PEERGROUPS) returned a huge number "
2070 "of groups (%lu bytes), ignoring",
2071 (unsigned long) len);
2072 goto out;
2073 }
2074
2075 converted_gids = dbus_new (dbus_gid_t, n_gids + 1);
2076
2077 if (converted_gids == NULL)
2078 {
2079 oom = TRUE;
2080 goto out;
2081 }
2082
2083 for (i = 0; i < n_gids; i++)
2084 {
2085 converted_gids[i] = (dbus_gid_t) buf[i];
2086
2087 if (converted_gids[i] == primary)
2088 need_primary = FALSE;
2089 }
2090
2091 if (need_primary && primary != DBUS_GID_UNSET)
2092 {
2093 converted_gids[n_gids] = primary;
2094 n_gids++;
2095 }
2096
2097 _dbus_credentials_take_unix_gids (credentials, converted_gids, n_gids);
2098
2099out:
2100 dbus_free (buf);
2101 return !oom;
2102#else
2103 /* no error */
2104 return TRUE;
2105#endif
2106}
2107
2108/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
2109static dbus_bool_t
2110add_linux_security_label_to_credentials (int client_fd,
2111 DBusCredentials *credentials)
2112{
2113#if defined(__linux__) && defined(SO_PEERSEC)
2114 DBusString buf;
2115 socklen_t len = 1024;
2116 dbus_bool_t oom = FALSE;
2117
2118 if (!_dbus_string_init_preallocated (&buf, len) ||
2119 !_dbus_string_set_length (&buf, len))
2120 return FALSE;
2121
2122 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
2123 _dbus_string_get_data (&buf), &len) < 0)
2124 {
2125 int e = errno;
2126
2127 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
2128 _dbus_strerror (e), (unsigned long) len);
2129
2130 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
2131 {
2132 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
2133 _dbus_strerror (e));
2134 goto out;
2135 }
2136
2137 /* If not enough space, len is updated to be enough.
2138 * Try again with a large enough buffer. */
2139 if (!_dbus_string_set_length (&buf, len))
2140 {
2141 oom = TRUE;
2142 goto out;
2143 }
2144
2145 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
2146 }
2147
2148 if (len <= 0)
2149 {
2150 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
2151 (unsigned long) len);
2152 goto out;
2153 }
2154
2155 if (len > _dbus_string_get_length_uint (&buf))
2156 {
2157 _dbus_verbose ("%lu > %u", (unsigned long) len,
2158 _dbus_string_get_length_uint (&buf));
2159 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
2160 }
2161
2162 if (_dbus_string_get_byte (&buf, len - 1) == 0)
2163 {
2164 /* the kernel included the trailing \0 in its count,
2165 * but DBusString always has an extra \0 after the data anyway */
2166 _dbus_verbose ("subtracting trailing \\0\n");
2167 len--;
2168 }
2169
2170 if (!_dbus_string_set_length (&buf, len))
2171 {
2172 _dbus_assert_not_reached ("shortening string should not lead to OOM");
2173 oom = TRUE;
2174 goto out;
2175 }
2176
2177 if (strlen (_dbus_string_get_const_data (&buf)) != len)
2178 {
2179 /* LSM people on the linux-security-module@ mailing list say this
2180 * should never happen: the label should be a bytestring with
2181 * an optional trailing \0 */
2182 _dbus_verbose ("security label from kernel had an embedded \\0, "
2183 "ignoring it\n");
2184 goto out;
2185 }
2186
2187 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
2188 (unsigned long) len,
2189 _dbus_string_get_const_data (&buf));
2190
2192 _dbus_string_get_const_data (&buf)))
2193 {
2194 oom = TRUE;
2195 goto out;
2196 }
2197
2198out:
2199 _dbus_string_free (&buf);
2200 return !oom;
2201#else
2202 /* no error */
2203 return TRUE;
2204#endif
2205}
2206
2249 DBusCredentials *credentials,
2250 DBusError *error)
2251{
2252 struct msghdr msg;
2253 struct iovec iov;
2254 char buf;
2255 dbus_uid_t uid_read;
2256 dbus_gid_t primary_gid_read;
2257 dbus_pid_t pid_read;
2258 int bytes_read;
2259 int pid_fd_read;
2260 unsigned int n_fds;
2261
2262#ifdef HAVE_CMSGCRED
2263 union {
2264 struct cmsghdr hdr;
2265 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
2266 } cmsg;
2267#elif defined(DBUS_ENABLE_INTRUSIVE_TESTS)
2268 /* To reproduce https://gitlab.freedesktop.org/dbus/dbus/-/work_items/588
2269 * on other platforms, by behaving as though struct cmsgcred was
2270 * supported */
2271 union {
2272 struct cmsghdr hdr;
2273 /* Just some random amount of space that is certainly enough to
2274 * hold some file descriptors */
2275 char fake_cred[CMSG_SPACE (1024)];
2276 } cmsg;
2277#endif
2278
2279 /* The POSIX spec certainly doesn't promise this, but
2280 * we need these assertions to fail as soon as we're wrong about
2281 * it so we can do the porting fixups
2282 */
2283 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2284 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2285 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2286
2287 uid_read = DBUS_UID_UNSET;
2288 primary_gid_read = DBUS_GID_UNSET;
2289 pid_read = DBUS_PID_UNSET;
2290 pid_fd_read = -1;
2291
2292 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2293
2294 _dbus_credentials_clear (credentials);
2295
2296 iov.iov_base = &buf;
2297 iov.iov_len = 1;
2298
2299 _DBUS_ZERO(msg);
2300 msg.msg_iov = &iov;
2301 msg.msg_iovlen = 1;
2302
2303#if defined(HAVE_CMSGCRED)
2304 _DBUS_ZERO(cmsg);
2305 msg.msg_control = (caddr_t) &cmsg;
2306 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
2307#elif defined(DBUS_ENABLE_INTRUSIVE_TESTS)
2308 _DBUS_ZERO (cmsg);
2309 msg.msg_control = &cmsg;
2310 msg.msg_controllen = sizeof (cmsg);
2311#endif
2312
2313 again:
2314 bytes_read = recvmsg (client_fd.fd, &msg, 0);
2315
2316 if (bytes_read < 0)
2317 {
2318 if (errno == EINTR)
2319 goto again;
2320
2321 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2322 * normally only call read_credentials if the socket was ready
2323 * for reading
2324 */
2325
2326 dbus_set_error (error, _dbus_error_from_errno (errno),
2327 "Failed to read credentials byte: %s",
2328 _dbus_strerror (errno));
2329 return FALSE;
2330 }
2331
2332 n_fds = 0;
2333
2334 if (!_dbus_socket_unpack_or_close_scm_rights (&msg, NULL, &n_fds))
2335 {
2336 /* The only way this can currently fail is ENOSPC,
2337 * representing MSG_CTRUNC, which would indicate that the message
2338 * had more SCM_RIGHTS fds than the 0 we were willing to accept. */
2340 "Credentials byte should not have had attached file descriptors");
2341 return FALSE;
2342 }
2343
2344 _dbus_assert (n_fds == 0);
2345
2346 if (bytes_read == 0)
2347 {
2348 /* this should not happen unless we are using recvmsg wrong,
2349 * so is essentially here for paranoia
2350 */
2352 "Failed to read credentials byte (zero-length read)");
2353 return FALSE;
2354 }
2355 else if (buf != '\0')
2356 {
2358 "Credentials byte was not nul");
2359 return FALSE;
2360 }
2361
2362 _dbus_verbose ("read credentials byte\n");
2363
2364 {
2365#ifdef SO_PEERCRED
2366 /* Supported by at least Linux and OpenBSD, with minor differences.
2367 *
2368 * This mechanism passes the process ID through and does not require
2369 * the peer's cooperation, so we prefer it over all others. Notably,
2370 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2371 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2372 * because this is much less fragile.
2373 */
2374#ifdef __OpenBSD__
2375 struct sockpeercred cr;
2376#else
2377 struct ucred cr;
2378#endif
2379 socklen_t cr_len = sizeof (cr);
2380
2381 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2382 {
2383 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2384 _dbus_strerror (errno));
2385 }
2386 else if (cr_len != sizeof (cr))
2387 {
2388 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2389 cr_len, (int) sizeof (cr));
2390 }
2391 else
2392 {
2393 if (cr.pid != 0)
2394 pid_read = cr.pid;
2395
2396 if (cr.uid != (uid_t)-1)
2397 uid_read = cr.uid;
2398#ifdef __linux__
2399 /* Do other platforms have cr.gid? (Not that it really matters,
2400 * because the gid is useless to us unless we know the complete
2401 * group vector, which we only know on Linux.) */
2402 if (cr.gid != (gid_t)-1)
2403 primary_gid_read = cr.gid;
2404#endif
2405 }
2406
2407#ifdef SO_PEERPIDFD
2408 /* If we have SO_PEERCRED we might also have SO_PEERPIDFD, which
2409 * allows to pin the process ID, and is available on Linux since v6.5. */
2410 cr_len = sizeof (int);
2411
2412 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERPIDFD, &pid_fd_read, &cr_len) != 0)
2413 {
2414 _dbus_verbose ("Failed to getsockopt(SO_PEERPIDFD): %s\n",
2415 _dbus_strerror (errno));
2416 }
2417 else if (cr_len != sizeof (int))
2418 {
2419 _dbus_verbose ("Failed to getsockopt(SO_PEERPIDFD), returned %d bytes, expected %d\n",
2420 cr_len, (int) sizeof (int));
2421 }
2422#endif
2423
2424#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2425 /* Another variant of the above - used on NetBSD
2426 */
2427 struct unpcbid cr;
2428 socklen_t cr_len = sizeof (cr);
2429
2430 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2431 {
2432 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2433 _dbus_strerror (errno));
2434 }
2435 else if (cr_len != sizeof (cr))
2436 {
2437 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2438 cr_len, (int) sizeof (cr));
2439 }
2440 else
2441 {
2442 pid_read = cr.unp_pid;
2443 uid_read = cr.unp_euid;
2444 }
2445#elif defined(HAVE_CMSGCRED)
2446 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2447 * presence of that struct implies SCM_CREDS. Supported by at least
2448 * FreeBSD and DragonflyBSD.
2449 *
2450 * This mechanism requires the peer to help us (it has to send us a
2451 * SCM_CREDS message) but it does pass the process ID through,
2452 * which makes it better than getpeereid().
2453 */
2454 struct cmsgcred *cred;
2455 struct cmsghdr *cmsgp;
2456
2457 for (cmsgp = CMSG_FIRSTHDR (&msg);
2458 cmsgp != NULL;
2459 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2460 {
2461 if (cmsgp->cmsg_type == SCM_CREDS &&
2462 cmsgp->cmsg_level == SOL_SOCKET &&
2463 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2464 {
2465 cred = (struct cmsgcred *) (void *) CMSG_DATA (cmsgp);
2466 pid_read = cred->cmcred_pid;
2467 uid_read = cred->cmcred_euid;
2468 break;
2469 }
2470 }
2471
2472#elif defined(HAVE_GETPEERUCRED)
2473 /* Supported in at least Solaris >= 10. It should probably be higher
2474 * up this list, because it carries the pid and we use this code path
2475 * for audit data. */
2476 ucred_t * ucred = NULL;
2477 if (getpeerucred (client_fd.fd, &ucred) == 0)
2478 {
2479#ifdef HAVE_ADT
2480 adt_session_data_t *adth = NULL;
2481#endif
2482 pid_read = ucred_getpid (ucred);
2483 uid_read = ucred_geteuid (ucred);
2484#ifdef HAVE_ADT
2485 /* generate audit session data based on socket ucred */
2486 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2487 {
2488 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2489 }
2490 else
2491 {
2492 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2493 {
2494 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2495 }
2496 else
2497 {
2498 adt_export_data_t *data = NULL;
2499 size_t size = adt_export_session_data (adth, &data);
2500 if (size <= 0)
2501 {
2502 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2503 }
2504 else
2505 {
2506 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2507 free (data);
2508 }
2509 }
2510 (void) adt_end_session (adth);
2511 }
2512#endif /* HAVE_ADT */
2513 }
2514 else
2515 {
2516 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2517 }
2518 if (ucred != NULL)
2519 ucred_free (ucred);
2520
2521 /* ----------------------------------------------------------------
2522 * When adding new mechanisms, please add them above this point
2523 * if they support passing the process ID through, or below if not.
2524 * ---------------------------------------------------------------- */
2525
2526#elif defined(HAVE_GETPEEREID)
2527 /* getpeereid() originates from D.J. Bernstein and is fairly
2528 * widely-supported. According to a web search, it might be present in
2529 * any/all of:
2530 *
2531 * - AIX?
2532 * - Blackberry?
2533 * - Cygwin
2534 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2535 * - Mac OS X
2536 * - Minix 3.1.8+
2537 * - MirBSD?
2538 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2539 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2540 * - QNX?
2541 */
2542 uid_t euid;
2543 gid_t egid;
2544 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2545 {
2546 uid_read = euid;
2547 }
2548 else
2549 {
2550 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2551 }
2552#else /* no supported mechanism */
2553
2554#warning Socket credentials not supported on this Unix OS
2555#warning Please tell https://gitlab.freedesktop.org/dbus/dbus/-/issues/new
2556
2557 /* Please add other operating systems known to support at least one of
2558 * the mechanisms above to this list, keeping alphabetical order.
2559 * Everything not in this list is best-effort.
2560 */
2561#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2562 defined(__linux__) || \
2563 defined(__OpenBSD__) || \
2564 defined(__NetBSD__)
2565# error Credentials passing not working on this OS is a regression!
2566#endif
2567
2568 _dbus_verbose ("Socket credentials not supported on this OS\n");
2569#endif
2570 }
2571
2572 _dbus_verbose ("Credentials:"
2573 " pid "DBUS_PID_FORMAT
2574 " uid "DBUS_UID_FORMAT
2575 "\n",
2576 pid_read,
2577 uid_read);
2578
2579 /* Assign this first, so we don't have to close it manually in case one of
2580 * the next steps fails. */
2581 if (pid_fd_read >= 0)
2582 _dbus_credentials_take_pid_fd (credentials, pid_fd_read);
2583
2584 if (pid_read != DBUS_PID_UNSET)
2585 {
2586 if (!_dbus_credentials_add_pid (credentials, pid_read))
2587 {
2588 _DBUS_SET_OOM (error);
2589 return FALSE;
2590 }
2591 }
2592
2593 if (uid_read != DBUS_UID_UNSET)
2594 {
2595 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2596 {
2597 _DBUS_SET_OOM (error);
2598 return FALSE;
2599 }
2600 }
2601
2602 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2603 {
2604 _DBUS_SET_OOM (error);
2605 return FALSE;
2606 }
2607
2608 /* We don't put any groups in the credentials unless we can put them
2609 * all there. */
2610 if (!add_groups_to_credentials (client_fd.fd, credentials, primary_gid_read))
2611 {
2612 _DBUS_SET_OOM (error);
2613 return FALSE;
2614 }
2615
2616 return TRUE;
2617}
2618
2638 DBusError *error)
2639{
2640 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2641
2642 if (write_credentials_byte (server_fd.fd, error))
2643 return TRUE;
2644 else
2645 return FALSE;
2646}
2647
2659{
2660 DBusSocket client_fd;
2661 struct sockaddr addr;
2662 socklen_t addrlen;
2663#ifdef HAVE_ACCEPT4
2664 dbus_bool_t cloexec_done;
2665#endif
2666
2667 addrlen = sizeof (addr);
2668
2669 retry:
2670
2671#ifdef HAVE_ACCEPT4
2672 /*
2673 * At compile-time, we assume that if accept4() is available in
2674 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2675 * not necessarily true that either is supported by the running kernel.
2676 */
2677 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2678 cloexec_done = client_fd.fd >= 0;
2679
2680 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2681#endif
2682 {
2683 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2684 }
2685
2686 if (client_fd.fd < 0)
2687 {
2688 if (errno == EINTR)
2689 goto retry;
2690 }
2691
2692 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2693
2694#ifdef HAVE_ACCEPT4
2695 if (!cloexec_done)
2696#endif
2697 {
2698 _dbus_fd_set_close_on_exec(client_fd.fd);
2699 }
2700
2701 return client_fd;
2702}
2703
2714{
2715 const char *directory;
2716 struct stat sb;
2717
2718 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2719
2720 directory = _dbus_string_get_const_data (dir);
2721
2722 if (stat (directory, &sb) < 0)
2723 {
2724 dbus_set_error (error, _dbus_error_from_errno (errno),
2725 "%s", _dbus_strerror (errno));
2726
2727 return FALSE;
2728 }
2729
2730 if (sb.st_uid != geteuid ())
2731 {
2733 "%s directory is owned by user %lu, not %lu",
2734 directory,
2735 (unsigned long) sb.st_uid,
2736 (unsigned long) geteuid ());
2737 return FALSE;
2738 }
2739
2740 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2741 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2742 {
2744 "%s directory is not private to the user", directory);
2745 return FALSE;
2746 }
2747
2748 return TRUE;
2749}
2750
2751static dbus_bool_t
2752fill_user_info_from_passwd (struct passwd *p,
2753 DBusUserInfo *info,
2754 DBusError *error)
2755{
2756 _dbus_assert (p->pw_name != NULL);
2757 _dbus_assert (p->pw_dir != NULL);
2758
2759 info->uid = p->pw_uid;
2760 info->primary_gid = p->pw_gid;
2761 info->username = _dbus_strdup (p->pw_name);
2762 info->homedir = _dbus_strdup (p->pw_dir);
2763
2764 if (info->username == NULL ||
2765 info->homedir == NULL)
2766 {
2768 return FALSE;
2769 }
2770
2771 return TRUE;
2772}
2773
2774static dbus_bool_t
2775fill_user_info (DBusUserInfo *info,
2776 dbus_uid_t uid,
2777 const DBusString *username,
2778 DBusError *error)
2779{
2780 const char *username_c;
2781
2782 /* exactly one of username/uid provided */
2783 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2784 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2785
2786 info->uid = DBUS_UID_UNSET;
2788 info->group_ids = NULL;
2789 info->n_group_ids = 0;
2790 info->username = NULL;
2791 info->homedir = NULL;
2792
2793 if (username != NULL)
2794 username_c = _dbus_string_get_const_data (username);
2795 else
2796 username_c = NULL;
2797
2798 /* For now assuming that the getpwnam() and getpwuid() flavors
2799 * are always symmetrical, if not we have to add more configure
2800 * checks
2801 */
2802
2803 {
2804 struct passwd *p;
2805 char *buf = NULL;
2806 int result;
2807#ifdef HAVE_GETPWNAM_R
2808 size_t buflen;
2809 struct passwd p_str;
2810
2811 /* retrieve maximum needed size for buf */
2812 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2813
2814 /* sysconf actually returns a long, but everything else expects size_t,
2815 * so just recast here.
2816 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2817 */
2818 if ((long) buflen <= 0)
2819 buflen = 1024;
2820
2821 result = -1;
2822 while (1)
2823 {
2824 buf = dbus_malloc (buflen);
2825 if (buf == NULL)
2826 {
2828 return FALSE;
2829 }
2830
2831 p = NULL;
2832 if (uid != DBUS_UID_UNSET)
2833 result = getpwuid_r (uid, &p_str, buf, buflen,
2834 &p);
2835 else
2836 result = getpwnam_r (username_c, &p_str, buf, buflen,
2837 &p);
2838 //Try a bigger buffer if ERANGE was returned
2839 if (result == ERANGE && buflen < 512 * 1024)
2840 {
2841 dbus_free (buf);
2842 buflen *= 2;
2843 }
2844 else
2845 {
2846 break;
2847 }
2848 }
2849
2850 /* There are three possibilities:
2851 * - an error: result is a nonzero error code, p should be NULL
2852 * - name or uid not found: result is 0, p is NULL
2853 * - success: result is 0, p should be &p_str
2854 *
2855 * Ensure that in all failure cases, p is set to NULL, matching the
2856 * getpwuid/getpwnam interface. */
2857 if (result != 0 || p != &p_str)
2858 p = NULL;
2859
2860#else /* ! HAVE_GETPWNAM_R */
2861 /* I guess we're screwed on thread safety here */
2862#warning getpwnam_r() not available, please report this to the dbus maintainers with details of your OS
2863
2864 /* It is unspecified whether "failed to find" counts as an error,
2865 * or whether it's reported as p == NULL without touching errno.
2866 * Reset errno so we can distinguish. */
2867 errno = 0;
2868
2869 if (uid != DBUS_UID_UNSET)
2870 p = getpwuid (uid);
2871 else
2872 p = getpwnam (username_c);
2873
2874 /* Always initialized, but only meaningful if p is NULL */
2875 result = errno;
2876#endif /* ! HAVE_GETPWNAM_R */
2877
2878 if (p != NULL)
2879 {
2880 if (!fill_user_info_from_passwd (p, info, error))
2881 {
2882 dbus_free (buf);
2883 return FALSE;
2884 }
2885 dbus_free (buf);
2886 }
2887 else
2888 {
2889 DBusError local_error = DBUS_ERROR_INIT;
2890 const char *error_str;
2891
2892 if (result == 0)
2893 error_str = "not found";
2894 else
2895 error_str = _dbus_strerror (result);
2896
2897 if (uid != DBUS_UID_UNSET)
2898 dbus_set_error (&local_error, _dbus_error_from_errno (result),
2899 "Looking up user ID " DBUS_UID_FORMAT ": %s",
2900 uid, error_str);
2901 else
2902 dbus_set_error (&local_error, _dbus_error_from_errno (result),
2903 "Looking up user \"%s\": %s",
2904 username_c ? username_c : "???", error_str);
2905
2906 _dbus_verbose ("%s", local_error.message);
2907 dbus_move_error (&local_error, error);
2908 dbus_free (buf);
2909 return FALSE;
2910 }
2911 }
2912
2913 /* Fill this in so we can use it to get groups */
2914 username_c = info->username;
2915
2916#ifdef HAVE_GETGROUPLIST
2917 {
2918 gid_t *buf;
2919 int buf_count;
2920 int i;
2921 int initial_buf_count;
2922
2923 initial_buf_count = 17;
2924 buf_count = initial_buf_count;
2925 buf = dbus_new (gid_t, buf_count);
2926 if (buf == NULL)
2927 {
2929 goto failed;
2930 }
2931
2932 if (getgrouplist (username_c,
2933 info->primary_gid,
2934 buf, &buf_count) < 0)
2935 {
2936 gid_t *new;
2937 /* Presumed cause of negative return code: buf has insufficient
2938 entries to hold the entire group list. The Linux behavior in this
2939 case is to pass back the actual number of groups in buf_count, but
2940 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2941 So as a hack, try to help out a bit by guessing a larger
2942 number of groups, within reason.. might still fail, of course,
2943 but we can at least print a more informative message. I looked up
2944 the "right way" to do this by downloading Apple's own source code
2945 for the "id" command, and it turns out that they use an
2946 undocumented library function getgrouplist_2 (!) which is not
2947 declared in any header in /usr/include (!!). That did not seem
2948 like the way to go here.
2949 */
2950 if (buf_count == initial_buf_count)
2951 {
2952 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2953 }
2954 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2955 if (new == NULL)
2956 {
2958 dbus_free (buf);
2959 goto failed;
2960 }
2961
2962 buf = new;
2963
2964 errno = 0;
2965 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2966 {
2967 if (errno == 0)
2968 {
2969 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2970 username_c, buf_count, buf_count);
2971 }
2972 else
2973 {
2974 dbus_set_error (error,
2975 _dbus_error_from_errno (errno),
2976 "Failed to get groups for username \"%s\" primary GID "
2977 DBUS_GID_FORMAT ": %s\n",
2978 username_c, info->primary_gid,
2979 _dbus_strerror (errno));
2980 dbus_free (buf);
2981 goto failed;
2982 }
2983 }
2984 }
2985
2986 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2987 if (info->group_ids == NULL)
2988 {
2990 dbus_free (buf);
2991 goto failed;
2992 }
2993
2994 for (i = 0; i < buf_count; ++i)
2995 info->group_ids[i] = buf[i];
2996
2997 info->n_group_ids = buf_count;
2998
2999 dbus_free (buf);
3000 }
3001#else /* HAVE_GETGROUPLIST */
3002 {
3003 /* We just get the one group ID */
3004 info->group_ids = dbus_new (dbus_gid_t, 1);
3005 if (info->group_ids == NULL)
3006 {
3008 goto failed;
3009 }
3010
3011 info->n_group_ids = 1;
3012
3013 (info->group_ids)[0] = info->primary_gid;
3014 }
3015#endif /* HAVE_GETGROUPLIST */
3016
3017 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3018
3019 return TRUE;
3020
3021 failed:
3022 _DBUS_ASSERT_ERROR_IS_SET (error);
3023 return FALSE;
3024}
3025
3036 const DBusString *username,
3037 DBusError *error)
3038{
3039 return fill_user_info (info, DBUS_UID_UNSET,
3040 username, error);
3041}
3042
3053 dbus_uid_t uid,
3054 DBusError *error)
3055{
3056 return fill_user_info (info, uid,
3057 NULL, error);
3058}
3059
3075{
3076 dbus_pid_t pid = _dbus_getpid ();
3077
3078 /* The POSIX spec certainly doesn't promise this, but
3079 * we need these assertions to fail as soon as we're wrong about
3080 * it so we can do the porting fixups
3081 */
3082 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
3083 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
3084 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
3085
3086#if HAVE_DECL_SYS_PIDFD_OPEN
3087 /* Normally this syscall would have a race condition, but we can trust
3088 * that our own process isn't going to exit, so the pid won't get reused. */
3089 int pid_fd = (int) syscall (SYS_pidfd_open, pid, 0);
3090 if (pid_fd >= 0)
3091 _dbus_credentials_take_pid_fd (credentials, pid_fd);
3092#endif
3093 if (!_dbus_credentials_add_pid (credentials, pid))
3094 return FALSE;
3095 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
3096 return FALSE;
3097
3098 return TRUE;
3099}
3100
3115{
3116#ifdef __linux__
3117 DBusError error = DBUS_ERROR_INIT;
3118 DBusString content = _DBUS_STRING_INIT_INVALID;
3119 DBusString filename = _DBUS_STRING_INIT_INVALID;
3120 dbus_pid_t result = DBUS_PID_UNSET;
3121 int pid_index;
3122
3123 if (pid_fd < 0)
3124 goto out;
3125
3126 if (!_dbus_string_init (&content))
3127 goto out;
3128
3129 if (!_dbus_string_init (&filename))
3130 goto out;
3131
3132 if (!_dbus_string_append_printf (&filename, "/proc/self/fdinfo/%d", pid_fd))
3133 goto out;
3134
3135 if (!_dbus_file_get_contents (&content, &filename, &error))
3136 {
3137 _dbus_verbose ("Cannot read '/proc/self/fdinfo/%d', unable to resolve PID, %s: %s\n",
3138 pid_fd, error.name, error.message);
3139 goto out;
3140 }
3141
3142 /* Ensure we are not reading PPid, either it's the first line of the file or
3143 * there's a newline before it. */
3144 if (!_dbus_string_find (&content, 0, "Pid:", &pid_index) ||
3145 (pid_index > 0 && _dbus_string_get_byte (&content, pid_index - 1) != '\n'))
3146 {
3147 _dbus_verbose ("Cannot find 'Pid:' in '/proc/self/fdinfo/%d', unable to resolve PID\n",
3148 pid_fd);
3149 goto out;
3150 }
3151
3152 if (!_dbus_string_parse_uint (&content, pid_index + strlen ("Pid:"), &result, NULL))
3153 {
3154 _dbus_verbose ("Cannot parse 'Pid:' from '/proc/self/fdinfo/%d', unable to resolve PID\n",
3155 pid_fd);
3156 goto out;
3157 }
3158
3159out:
3160 _dbus_string_free (&content);
3161 _dbus_string_free (&filename);
3162 dbus_error_free (&error);
3163
3164 if (result <= 0)
3165 return DBUS_PID_UNSET;
3166
3167 return result;
3168#else
3169 return DBUS_PID_UNSET;
3170#endif
3171
3172}
3173
3190
3197{
3198 return getpid ();
3199}
3200
3206{
3207 return getuid ();
3208}
3209
3215{
3216 return geteuid ();
3217}
3218
3225unsigned long
3227{
3228 return getpid ();
3229}
3230
3231#if !defined(HAVE_STDATOMIC_H) && !DBUS_USE_SYNC
3232/* To be thread-safe by default on platforms that don't necessarily have
3233 * atomic operations (notably Debian armel, which is armv4t), we must
3234 * use a mutex that can be initialized statically, like this.
3235 * GLib >= 2.32 uses a similar system.
3236 */
3237static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
3238#endif
3239
3248{
3249#ifdef HAVE_STDATOMIC_H
3250 /* Atomic version of "old = *atomic; *atomic += 1; return old" */
3251 return atomic_fetch_add (&atomic->value, 1);
3252#elif DBUS_USE_SYNC
3253 /* Atomic version of "*atomic += 1; return *atomic - 1" */
3254 return __sync_add_and_fetch(&atomic->value, 1)-1;
3255#else
3256 dbus_int32_t res;
3257
3258 pthread_mutex_lock (&atomic_mutex);
3259 res = atomic->value;
3260 atomic->value += 1;
3261 pthread_mutex_unlock (&atomic_mutex);
3262
3263 return res;
3264#endif
3265}
3266
3275{
3276#ifdef HAVE_STDATOMIC_H
3277 /* Atomic version of "old = *atomic; *atomic -= 1; return old" */
3278 return atomic_fetch_sub (&atomic->value, 1);
3279#elif DBUS_USE_SYNC
3280 /* Atomic version of "*atomic -= 1; return *atomic + 1" */
3281 return __sync_sub_and_fetch(&atomic->value, 1)+1;
3282#else
3283 dbus_int32_t res;
3284
3285 pthread_mutex_lock (&atomic_mutex);
3286 res = atomic->value;
3287 atomic->value -= 1;
3288 pthread_mutex_unlock (&atomic_mutex);
3289
3290 return res;
3291#endif
3292}
3293
3303{
3304#ifdef HAVE_STDATOMIC_H
3305 /* Atomic version of "return *atomic" */
3306 return atomic_load (&atomic->value);
3307#elif DBUS_USE_SYNC
3308 __sync_synchronize ();
3309 return atomic->value;
3310#else
3311 dbus_int32_t res;
3312
3313 pthread_mutex_lock (&atomic_mutex);
3314 res = atomic->value;
3315 pthread_mutex_unlock (&atomic_mutex);
3316
3317 return res;
3318#endif
3319}
3320
3326void
3328{
3329#ifdef HAVE_STDATOMIC_H
3330 /* Atomic version of "*atomic = 0" */
3331 atomic_store (&atomic->value, 0);
3332#elif DBUS_USE_SYNC
3333 /* Atomic version of "*atomic &= 0; return *atomic" */
3334 __sync_and_and_fetch (&atomic->value, 0);
3335#else
3336 pthread_mutex_lock (&atomic_mutex);
3337 atomic->value = 0;
3338 pthread_mutex_unlock (&atomic_mutex);
3339#endif
3340}
3341
3347void
3349{
3350#ifdef HAVE_STDATOMIC_H
3351 /* Atomic version of "*atomic = 1" */
3352 atomic_store (&atomic->value, 1);
3353#elif DBUS_USE_SYNC
3354 /* Atomic version of "*atomic |= 1; return *atomic" */
3355 __sync_or_and_fetch (&atomic->value, 1);
3356#else
3357 pthread_mutex_lock (&atomic_mutex);
3358 atomic->value = 1;
3359 pthread_mutex_unlock (&atomic_mutex);
3360#endif
3361}
3362
3371int
3373 int n_fds,
3374 int timeout_milliseconds)
3375{
3376#if defined(HAVE_POLL) && !defined(BROKEN_POLL)
3377 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
3378 if (timeout_milliseconds < -1)
3379 {
3380 timeout_milliseconds = -1;
3381 }
3382
3383 return poll (fds,
3384 n_fds,
3385 timeout_milliseconds);
3386#else /* ! HAVE_POLL */
3387 /* Emulate poll() in terms of select() */
3388 fd_set read_set, write_set, err_set;
3389 int max_fd = 0;
3390 int i;
3391 struct timeval tv;
3392 int ready = 0;
3393
3394 FD_ZERO (&read_set);
3395 FD_ZERO (&write_set);
3396 FD_ZERO (&err_set);
3397
3398 for (i = 0; i < n_fds; i++)
3399 {
3400 DBusPollFD *fdp = &fds[i];
3401
3402 fdp->revents = 0;
3403
3404 /* poll(2) documents that fd < 0 is ignored
3405 * (no events will be reported) */
3406 if (fdp->fd < 0)
3407 continue;
3408
3409 if (fdp->fd >= FD_SETSIZE)
3410 {
3411 fdp->revents = _DBUS_POLLNVAL;
3412 ready++;
3413 continue;
3414 }
3415
3416 if (fdp->events & _DBUS_POLLIN)
3417 FD_SET (fdp->fd, &read_set);
3418
3419 if (fdp->events & _DBUS_POLLOUT)
3420 FD_SET (fdp->fd, &write_set);
3421
3422 FD_SET (fdp->fd, &err_set);
3423
3424 max_fd = MAX (max_fd, fdp->fd);
3425 }
3426
3427 if (ready > 0)
3428 return ready;
3429
3430 tv.tv_sec = timeout_milliseconds / 1000;
3431 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
3432
3433 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
3434 timeout_milliseconds < 0 ? NULL : &tv);
3435
3436 if (ready < 0 && errno == EBADF)
3437 {
3438 ready = 0;
3439
3440 /* One of the file descriptors we were asked to poll was invalid.
3441 * Can we tell which one? */
3442 for (i = 0; i < n_fds; i++)
3443 {
3444 DBusPollFD *fdp = &fds[i];
3445 int res;
3446
3447 res = fcntl (fdp->fd, F_GETFD, 0);
3448
3449 if (res == -1 && errno == EBADF)
3450 {
3451 fdp->revents = _DBUS_POLLNVAL;
3452 ready++;
3453 }
3454 }
3455
3456 if (ready > 0)
3457 {
3458 /* We can report at least one fd as POLLNVAL. Good enough! */
3459 return ready;
3460 }
3461 else
3462 {
3463 /* One of the fds was invalid, but when we went back and looked at
3464 * them all, none still appeared to be invalid.
3465 * Give up and report the error as select() would. */
3466 errno = EBADF;
3467 return -1;
3468 }
3469 }
3470
3471 if (ready > 0)
3472 {
3473 for (i = 0; i < n_fds; i++)
3474 {
3475 DBusPollFD *fdp = &fds[i];
3476
3477 if (fdp->fd < 0)
3478 continue;
3479
3480 if (FD_ISSET (fdp->fd, &read_set))
3481 fdp->revents |= _DBUS_POLLIN;
3482
3483 if (FD_ISSET (fdp->fd, &write_set))
3484 fdp->revents |= _DBUS_POLLOUT;
3485
3486 if (FD_ISSET (fdp->fd, &err_set))
3487 fdp->revents |= _DBUS_POLLERR;
3488 }
3489 }
3490
3491 return ready;
3492#endif
3493}
3494
3502void
3504 long *tv_usec)
3505{
3506#ifdef HAVE_MONOTONIC_CLOCK
3507 struct timespec ts;
3508 clock_gettime (CLOCK_MONOTONIC, &ts);
3509
3510 if (tv_sec)
3511 *tv_sec = ts.tv_sec;
3512 if (tv_usec)
3513 *tv_usec = ts.tv_nsec / 1000;
3514#else
3515 struct timeval t;
3516
3517 gettimeofday (&t, NULL);
3518
3519 if (tv_sec)
3520 *tv_sec = t.tv_sec;
3521 if (tv_usec)
3522 *tv_usec = t.tv_usec;
3523#endif
3524}
3525
3533void
3535 long *tv_usec)
3536{
3537 struct timeval t;
3538
3539 gettimeofday (&t, NULL);
3540
3541 if (tv_sec)
3542 *tv_sec = t.tv_sec;
3543 if (tv_usec)
3544 *tv_usec = t.tv_usec;
3545}
3546
3557 DBusError *error)
3558{
3559 const char *filename_c;
3560
3561 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3562
3563 filename_c = _dbus_string_get_const_data (filename);
3564
3565 if (mkdir (filename_c, 0700) < 0)
3566 {
3567 if (errno == EEXIST)
3568 return TRUE;
3569
3571 "Failed to create directory %s: %s\n",
3572 filename_c, _dbus_strerror (errno));
3573 return FALSE;
3574 }
3575 else
3576 return TRUE;
3577}
3578
3589 DBusError *error)
3590{
3591 const char *filename_c;
3592
3593 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3594
3595 filename_c = _dbus_string_get_const_data (filename);
3596
3597 if (mkdir (filename_c, 0700) < 0)
3598 {
3600 "Failed to create directory %s: %s\n",
3601 filename_c, _dbus_strerror (errno));
3602 return FALSE;
3603 }
3604 else
3605 return TRUE;
3606}
3607
3620 const DBusString *next_component)
3621{
3622 dbus_bool_t dir_ends_in_slash;
3623 dbus_bool_t file_starts_with_slash;
3624
3625 if (_dbus_string_get_length (dir) == 0 ||
3626 _dbus_string_get_length (next_component) == 0)
3627 return TRUE;
3628
3629 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3630 _dbus_string_get_length (dir) - 1);
3631
3632 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3633
3634 if (dir_ends_in_slash && file_starts_with_slash)
3635 {
3636 _dbus_string_shorten (dir, 1);
3637 }
3638 else if (!(dir_ends_in_slash || file_starts_with_slash))
3639 {
3640 if (!_dbus_string_append_byte (dir, '/'))
3641 return FALSE;
3642 }
3643
3644 return _dbus_string_copy (next_component, 0, dir,
3645 _dbus_string_get_length (dir));
3646}
3647
3649#define NANOSECONDS_PER_SECOND 1000000000
3651#define MICROSECONDS_PER_SECOND 1000000
3653#define MILLISECONDS_PER_SECOND 1000
3655#define NANOSECONDS_PER_MILLISECOND 1000000
3657#define MICROSECONDS_PER_MILLISECOND 1000
3658
3663void
3665{
3666#ifdef HAVE_NANOSLEEP
3667 struct timespec req;
3668 struct timespec rem;
3669
3670 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3671 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3672 rem.tv_sec = 0;
3673 rem.tv_nsec = 0;
3674
3675 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3676 req = rem;
3677#elif defined (HAVE_USLEEP)
3678 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3679#else /* ! HAVE_USLEEP */
3680 sleep (MAX (milliseconds / 1000, 1));
3681#endif
3682}
3683
3695 int n_bytes,
3696 DBusError *error)
3697{
3698 int old_len = _dbus_string_get_length (str);
3699 int fd;
3700 int result;
3701#ifdef HAVE_GETRANDOM
3702 char *buffer;
3703
3704 if (!_dbus_string_lengthen (str, n_bytes))
3705 {
3706 _DBUS_SET_OOM (error);
3707 return FALSE;
3708 }
3709
3710 buffer = _dbus_string_get_data_len (str, old_len, n_bytes);
3711 result = getrandom (buffer, n_bytes, GRND_NONBLOCK);
3712
3713 if (result == n_bytes)
3714 return TRUE;
3715
3716 _dbus_string_set_length (str, old_len);
3717#endif
3718
3719 /* note, urandom on linux will fall back to pseudorandom */
3720 fd = open ("/dev/urandom", O_RDONLY);
3721
3722 if (fd < 0)
3723 {
3724 dbus_set_error (error, _dbus_error_from_errno (errno),
3725 "Could not open /dev/urandom: %s",
3726 _dbus_strerror (errno));
3727 return FALSE;
3728 }
3729
3730 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3731
3732 result = _dbus_read (fd, str, n_bytes);
3733
3734 if (result != n_bytes)
3735 {
3736 if (result < 0)
3737 dbus_set_error (error, _dbus_error_from_errno (errno),
3738 "Could not read /dev/urandom: %s",
3739 _dbus_strerror (errno));
3740 else
3742 "Short read from /dev/urandom");
3743
3744 _dbus_close (fd, NULL);
3745 _dbus_string_set_length (str, old_len);
3746 return FALSE;
3747 }
3748
3749 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3750 n_bytes);
3751
3752 _dbus_close (fd, NULL);
3753
3754 return TRUE;
3755}
3756
3762void
3763_dbus_exit (int code)
3764{
3765 _exit (code);
3766}
3767
3776const char*
3777_dbus_strerror (int error_number)
3778{
3779 const char *msg;
3780
3781 msg = strerror (error_number);
3782 if (msg == NULL)
3783 msg = "unknown";
3784
3785 return msg;
3786}
3787
3791void
3793{
3794 signal (SIGPIPE, SIG_IGN);
3795}
3796
3804void
3806{
3807 int val;
3808
3809 val = fcntl (fd, F_GETFD, 0);
3810
3811 if (val < 0)
3812 return;
3813
3814 val |= FD_CLOEXEC;
3815
3816 fcntl (fd, F_SETFD, val);
3817}
3818
3826void
3828{
3829 int val;
3830
3831 val = fcntl (fd, F_GETFD, 0);
3832
3833 if (val < 0)
3834 return;
3835
3836 val &= ~FD_CLOEXEC;
3837
3838 fcntl (fd, F_SETFD, val);
3839}
3840
3850 DBusError *error)
3851{
3852 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3853
3854 again:
3855 if (close (fd) < 0)
3856 {
3857 if (errno == EINTR)
3858 goto again;
3859
3860 dbus_set_error (error, _dbus_error_from_errno (errno),
3861 "Could not close fd %d", fd);
3862 return FALSE;
3863 }
3864
3865 return TRUE;
3866}
3867
3876int
3878 DBusError *error)
3879{
3880 int new_fd;
3881
3882#ifdef F_DUPFD_CLOEXEC
3883 dbus_bool_t cloexec_done;
3884
3885 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3886 cloexec_done = new_fd >= 0;
3887
3888 if (new_fd < 0 && errno == EINVAL)
3889#endif
3890 {
3891 new_fd = fcntl(fd, F_DUPFD, 3);
3892 }
3893
3894 if (new_fd < 0) {
3895
3896 dbus_set_error (error, _dbus_error_from_errno (errno),
3897 "Could not duplicate fd %d", fd);
3898 return -1;
3899 }
3900
3901#ifdef F_DUPFD_CLOEXEC
3902 if (!cloexec_done)
3903#endif
3904 {
3906 }
3907
3908 return new_fd;
3909}
3910
3920 DBusError *error)
3921{
3922 return _dbus_set_fd_nonblocking (fd.fd, error);
3923}
3924
3925static dbus_bool_t
3926_dbus_set_fd_nonblocking (int fd,
3927 DBusError *error)
3928{
3929 int val;
3930
3931 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3932
3933 val = fcntl (fd, F_GETFL, 0);
3934 if (val < 0)
3935 {
3936 dbus_set_error (error, _dbus_error_from_errno (errno),
3937 "Failed to get flags from file descriptor %d: %s",
3938 fd, _dbus_strerror (errno));
3939 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3940 _dbus_strerror (errno));
3941 return FALSE;
3942 }
3943
3944 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3945 {
3946 dbus_set_error (error, _dbus_error_from_errno (errno),
3947 "Failed to set nonblocking flag of file descriptor %d: %s",
3948 fd, _dbus_strerror (errno));
3949 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3950 fd, _dbus_strerror (errno));
3951
3952 return FALSE;
3953 }
3954
3955 return TRUE;
3956}
3957
3963void
3964_dbus_print_backtrace (void)
3965{
3966#if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3967 void *bt[500];
3968 int bt_size;
3969 int i;
3970 char **syms;
3971
3972 bt_size = backtrace (bt, 500);
3973
3974 syms = backtrace_symbols (bt, bt_size);
3975
3976 i = 0;
3977 while (i < bt_size)
3978 {
3979 /* don't use dbus_warn since it can _dbus_abort() */
3980 fprintf (stderr, " %s\n", syms[i]);
3981 ++i;
3982 }
3983 fflush (stderr);
3984
3985 free (syms);
3986#elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3987 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3988#else
3989 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3990#endif
3991}
3992
4007 DBusSocket *fd2,
4008 dbus_bool_t blocking,
4009 DBusError *error)
4010{
4011#ifdef HAVE_SOCKETPAIR
4012 int fds[2];
4013 int retval;
4014
4015#ifdef SOCK_CLOEXEC
4016 dbus_bool_t cloexec_done;
4017
4018 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
4019 cloexec_done = retval >= 0;
4020
4021 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
4022#endif
4023 {
4024 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
4025 }
4026
4027 if (retval < 0)
4028 {
4029 dbus_set_error (error, _dbus_error_from_errno (errno),
4030 "Could not create full-duplex pipe");
4031 return FALSE;
4032 }
4033
4034 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4035
4036#ifdef SOCK_CLOEXEC
4037 if (!cloexec_done)
4038#endif
4039 {
4042 }
4043
4044 if (!blocking &&
4045 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
4046 !_dbus_set_fd_nonblocking (fds[1], NULL)))
4047 {
4048 dbus_set_error (error, _dbus_error_from_errno (errno),
4049 "Could not set full-duplex pipe nonblocking");
4050
4051 _dbus_close (fds[0], NULL);
4052 _dbus_close (fds[1], NULL);
4053
4054 return FALSE;
4055 }
4056
4057 fd1->fd = fds[0];
4058 fd2->fd = fds[1];
4059
4060 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
4061 fd1->fd, fd2->fd);
4062
4063 return TRUE;
4064#else
4065 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
4067 "_dbus_socketpair() not implemented on this OS");
4068 return FALSE;
4069#endif
4070}
4071
4080int
4082 va_list args)
4083{
4084 char static_buf[1024];
4085 int bufsize = sizeof (static_buf);
4086 int len;
4087 va_list args_copy;
4088
4089 va_copy (args_copy, args);
4090 len = vsnprintf (static_buf, bufsize, format, args_copy);
4091 va_end (args_copy);
4092
4093 /* If vsnprintf() returned non-negative, then either the string fits in
4094 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
4095 * returns the number of characters that were needed, or this OS returns the
4096 * truncated length.
4097 *
4098 * We ignore the possibility that snprintf might just ignore the length and
4099 * overrun the buffer (64-bit Solaris 7), because that's pathological.
4100 * If your libc is really that bad, come back when you have a better one. */
4101 if (len == bufsize)
4102 {
4103 /* This could be the truncated length (Tru64 and IRIX have this bug),
4104 * or the real length could be coincidentally the same. Which is it?
4105 * If vsnprintf returns the truncated length, we'll go to the slow
4106 * path. */
4107 va_copy (args_copy, args);
4108
4109 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
4110 len = -1;
4111
4112 va_end (args_copy);
4113 }
4114
4115 /* If vsnprintf() returned negative, we have to do more work.
4116 * HP-UX returns negative. */
4117 while (len < 0)
4118 {
4119 char *buf;
4120
4121 bufsize *= 2;
4122
4123 buf = dbus_malloc (bufsize);
4124
4125 if (buf == NULL)
4126 return -1;
4127
4128 va_copy (args_copy, args);
4129 len = vsnprintf (buf, bufsize, format, args_copy);
4130 va_end (args_copy);
4131
4132 dbus_free (buf);
4133
4134 /* If the reported length is exactly the buffer size, round up to the
4135 * next size, in case vsnprintf has been returning the truncated
4136 * length */
4137 if (len == bufsize)
4138 len = -1;
4139 }
4140
4141 return len;
4142}
4143
4150const char*
4152{
4153 /* Protected by _DBUS_LOCK_sysdeps */
4154 static const char* tmpdir = NULL;
4155
4156 if (!_DBUS_LOCK (sysdeps))
4157 return NULL;
4158
4159 if (tmpdir == NULL)
4160 {
4161 /* TMPDIR is what glibc uses, then
4162 * glibc falls back to the P_tmpdir macro which
4163 * just expands to "/tmp"
4164 */
4165 if (tmpdir == NULL)
4166 tmpdir = getenv("TMPDIR");
4167
4168 /* These two env variables are probably
4169 * broken, but maybe some OS uses them?
4170 */
4171 if (tmpdir == NULL)
4172 tmpdir = getenv("TMP");
4173 if (tmpdir == NULL)
4174 tmpdir = getenv("TEMP");
4175
4176 /* And this is the sane fallback. */
4177 if (tmpdir == NULL)
4178 tmpdir = "/tmp";
4179 }
4180
4181 _DBUS_UNLOCK (sysdeps);
4182
4183 _dbus_assert(tmpdir != NULL);
4184
4185 return tmpdir;
4186}
4187
4188#if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
4208static dbus_bool_t
4209_read_subprocess_line_argv (const char *progpath,
4210 dbus_bool_t path_fallback,
4211 const char * const *argv,
4212 DBusString *result,
4213 DBusError *error)
4214{
4215 int result_pipe[2] = { -1, -1 };
4216 int errors_pipe[2] = { -1, -1 };
4217 pid_t pid;
4218 int ret;
4219 int status;
4220 int orig_len;
4221
4222 dbus_bool_t retval;
4223 sigset_t new_set, old_set;
4224
4225 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4226 retval = FALSE;
4227
4228 /* We need to block any existing handlers for SIGCHLD temporarily; they
4229 * will cause waitpid() below to fail.
4230 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
4231 */
4232 sigemptyset (&new_set);
4233 sigaddset (&new_set, SIGCHLD);
4234 sigprocmask (SIG_BLOCK, &new_set, &old_set);
4235
4236 orig_len = _dbus_string_get_length (result);
4237
4238#define READ_END 0
4239#define WRITE_END 1
4240 if (pipe (result_pipe) < 0)
4241 {
4242 dbus_set_error (error, _dbus_error_from_errno (errno),
4243 "Failed to create a pipe to call %s: %s",
4244 progpath, _dbus_strerror (errno));
4245 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
4246 progpath, _dbus_strerror (errno));
4247 goto out;
4248 }
4249 if (pipe (errors_pipe) < 0)
4250 {
4251 dbus_set_error (error, _dbus_error_from_errno (errno),
4252 "Failed to create a pipe to call %s: %s",
4253 progpath, _dbus_strerror (errno));
4254 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
4255 progpath, _dbus_strerror (errno));
4256 goto out;
4257 }
4258
4259 /* Make sure our output buffers aren't redundantly printed by both the
4260 * parent and the child */
4261 fflush (stdout);
4262 fflush (stderr);
4263
4264 pid = fork ();
4265 if (pid < 0)
4266 {
4267 dbus_set_error (error, _dbus_error_from_errno (errno),
4268 "Failed to fork() to call %s: %s",
4269 progpath, _dbus_strerror (errno));
4270 _dbus_verbose ("Failed to fork() to call %s: %s\n",
4271 progpath, _dbus_strerror (errno));
4272 goto out;
4273 }
4274
4275 if (pid == 0)
4276 {
4277 /* child process */
4278 const char *error_str;
4279
4280 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
4281 {
4282 int saved_errno = errno;
4283
4284 /* Try to write details into the pipe, but don't bother
4285 * trying too hard (no retry loop). */
4286
4287 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
4288 write (errors_pipe[WRITE_END], ": ", 2) < 0)
4289 {
4290 /* ignore, not much we can do */
4291 }
4292
4293 error_str = _dbus_strerror (saved_errno);
4294
4295 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
4296 {
4297 /* ignore, not much we can do */
4298 }
4299
4300 _exit (1);
4301 }
4302
4303 /* set-up stdXXX */
4304 close (result_pipe[READ_END]);
4305 close (errors_pipe[READ_END]);
4306
4307 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
4308 _exit (1);
4309 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
4310 _exit (1);
4311
4312 _dbus_close_all ();
4313
4314 sigprocmask (SIG_SETMASK, &old_set, NULL);
4315
4316 /* If it looks fully-qualified, try execv first */
4317 if (progpath[0] == '/')
4318 {
4319 execv (progpath, (char * const *) argv);
4320 /* Ok, that failed. Now if path_fallback is given, let's
4321 * try unqualified. This is mostly a hack to work
4322 * around systems which ship dbus-launch in /usr/bin
4323 * but everything else in /bin (because dbus-launch
4324 * depends on X11).
4325 */
4326 if (path_fallback)
4327 /* We must have a slash, because we checked above */
4328 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
4329 }
4330 else
4331 execvp (progpath, (char * const *) argv);
4332
4333 /* still nothing, we failed */
4334 _exit (1);
4335 }
4336
4337 /* parent process */
4338 close (result_pipe[WRITE_END]);
4339 close (errors_pipe[WRITE_END]);
4340 result_pipe[WRITE_END] = -1;
4341 errors_pipe[WRITE_END] = -1;
4342
4343 ret = 0;
4344 do
4345 {
4346 ret = _dbus_read (result_pipe[READ_END], result, 1024);
4347 }
4348 while (ret > 0);
4349
4350 /* reap the child process to avoid it lingering as zombie */
4351 do
4352 {
4353 ret = waitpid (pid, &status, 0);
4354 }
4355 while (ret == -1 && errno == EINTR);
4356
4357 /* We succeeded if the process exited with status 0 and
4358 anything was read */
4359 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
4360 {
4361 /* The process ended with error */
4362 DBusString error_message;
4363 if (!_dbus_string_init (&error_message))
4364 {
4365 _DBUS_SET_OOM (error);
4366 goto out;
4367 }
4368
4369 ret = 0;
4370 do
4371 {
4372 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
4373 }
4374 while (ret > 0);
4375
4376 _dbus_string_set_length (result, orig_len);
4377 if (_dbus_string_get_length (&error_message) > 0)
4379 "%s terminated abnormally with the following error: %s",
4380 progpath, _dbus_string_get_data (&error_message));
4381 else
4383 "%s terminated abnormally without any error message",
4384 progpath);
4385 _dbus_string_free (&error_message);
4386 goto out;
4387 }
4388
4389 retval = TRUE;
4390
4391 out:
4392 sigprocmask (SIG_SETMASK, &old_set, NULL);
4393
4394 _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
4395
4396 if (result_pipe[0] != -1)
4397 close (result_pipe[0]);
4398 if (result_pipe[1] != -1)
4399 close (result_pipe[1]);
4400 if (errors_pipe[0] != -1)
4401 close (errors_pipe[0]);
4402 if (errors_pipe[1] != -1)
4403 close (errors_pipe[1]);
4404
4405 return retval;
4406}
4407#endif
4408
4423 DBusString *address,
4424 DBusError *error)
4425{
4426#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
4427 static const char arg_dbus_launch[] = "dbus-launch";
4428 static const char arg_autolaunch[] = "--autolaunch";
4429 static const char arg_binary_syntax[] = "--binary-syntax";
4430 static const char arg_close_stderr[] = "--close-stderr";
4431
4432 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
4433 * but that's done elsewhere, and if it worked, this function wouldn't
4434 * be called.) */
4435 const char *display;
4436 const char *progpath;
4437 const char *argv[6];
4438 int i;
4439 DBusString uuid;
4440 dbus_bool_t retval;
4441
4442 if (_dbus_check_setuid ())
4443 {
4445 "Unable to autolaunch when setuid");
4446 return FALSE;
4447 }
4448
4449 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4450 retval = FALSE;
4451
4452 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
4453 * dbus-launch-x11 is just going to fail. Rather than trying to
4454 * run it, we might as well bail out early with a nice error.
4455 *
4456 * This is not strictly true in a world where the user bus exists,
4457 * because dbus-launch --autolaunch knows how to connect to that -
4458 * but if we were going to connect to the user bus, we'd have done
4459 * so before trying autolaunch: in any case. */
4460 display = _dbus_getenv ("DISPLAY");
4461
4462 if (display == NULL || display[0] == '\0')
4463 {
4465 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
4466 return FALSE;
4467 }
4468
4469 if (!_dbus_string_init (&uuid))
4470 {
4471 _DBUS_SET_OOM (error);
4472 return FALSE;
4473 }
4474
4475 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
4476 {
4477 goto out;
4478 }
4479
4480#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4481 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
4482
4483 if (progpath == NULL)
4484#endif
4485 progpath = DBUS_BINDIR "/dbus-launch";
4486 /*
4487 * argv[0] is always dbus-launch, that's the name what we'll
4488 * get from /proc, or ps(1), regardless what the progpath is,
4489 * see fd.o#69716
4490 */
4491 i = 0;
4492 argv[i] = arg_dbus_launch;
4493 ++i;
4494 argv[i] = arg_autolaunch;
4495 ++i;
4496 argv[i] = _dbus_string_get_data (&uuid);
4497 ++i;
4498 argv[i] = arg_binary_syntax;
4499 ++i;
4500 argv[i] = arg_close_stderr;
4501 ++i;
4502 argv[i] = NULL;
4503 ++i;
4504
4505 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4506
4507 retval = _read_subprocess_line_argv (progpath,
4508 TRUE,
4509 argv, address, error);
4510
4511 out:
4512 _dbus_string_free (&uuid);
4513 return retval;
4514#else
4516 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
4517#ifdef DBUS_ENABLE_LAUNCHD
4518 "verify that org.freedesktop.dbus-session.plist is loaded or "
4519#endif
4520 "set your DBUS_SESSION_BUS_ADDRESS instead");
4521 return FALSE;
4522#endif
4523}
4524
4545 dbus_bool_t create_if_not_found,
4546 DBusError *error)
4547{
4548 DBusError our_error = DBUS_ERROR_INIT;
4549 DBusError etc_error = DBUS_ERROR_INIT;
4550 DBusString filename;
4551 dbus_bool_t b;
4552
4553 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4554
4555 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
4556 if (b)
4557 return TRUE;
4558
4559 /* Fallback to the system machine ID */
4560 _dbus_string_init_const (&filename, "/etc/machine-id");
4561 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
4562
4563 if (b)
4564 {
4565 if (create_if_not_found)
4566 {
4567 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
4568 * complain if that isn't possible for whatever reason */
4569 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4570 _dbus_write_uuid_file (&filename, machine_id, NULL);
4571 }
4572
4573 dbus_error_free (&our_error);
4574 return TRUE;
4575 }
4576
4577 if (!create_if_not_found)
4578 {
4579 dbus_set_error (error, etc_error.name,
4580 "D-Bus library appears to be incorrectly set up: "
4581 "see the manual page for dbus-uuidgen to correct "
4582 "this issue. (%s; %s)",
4583 our_error.message, etc_error.message);
4584 dbus_error_free (&our_error);
4585 dbus_error_free (&etc_error);
4586 return FALSE;
4587 }
4588
4589 dbus_error_free (&our_error);
4590 dbus_error_free (&etc_error);
4591
4592 /* if none found, try to make a new one */
4593 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4594
4595 if (!_dbus_generate_uuid (machine_id, error))
4596 return FALSE;
4597
4598 return _dbus_write_uuid_file (&filename, machine_id, error);
4599}
4600
4610 const char *launchd_env_var,
4611 DBusError *error)
4612{
4613#ifdef DBUS_ENABLE_LAUNCHD
4614 char *argv[4];
4615 int i;
4616
4617 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4618
4619 if (_dbus_check_setuid ())
4620 {
4622 "Unable to find launchd socket when setuid");
4623 return FALSE;
4624 }
4625
4626 i = 0;
4627 argv[i] = "launchctl";
4628 ++i;
4629 argv[i] = "getenv";
4630 ++i;
4631 argv[i] = (char*)launchd_env_var;
4632 ++i;
4633 argv[i] = NULL;
4634 ++i;
4635
4636 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4637
4638 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4639 {
4640 return FALSE;
4641 }
4642
4643 /* no error, but no result either */
4644 if (_dbus_string_get_length(socket_path) == 0)
4645 {
4646 return FALSE;
4647 }
4648
4649 /* strip the carriage-return */
4650 _dbus_string_shorten(socket_path, 1);
4651 return TRUE;
4652#else /* DBUS_ENABLE_LAUNCHD */
4654 "can't lookup socket from launchd; launchd support not compiled in");
4655 return FALSE;
4656#endif
4657}
4658
4659#ifdef DBUS_ENABLE_LAUNCHD
4660static dbus_bool_t
4661_dbus_lookup_session_address_launchd (dbus_bool_t *supported,
4662 DBusString *address,
4663 DBusError *error)
4664{
4665 dbus_bool_t valid_socket;
4666 DBusString socket_path;
4667
4668 if (!_dbus_string_init (&socket_path))
4669 {
4670 _DBUS_SET_OOM (error);
4671 return FALSE;
4672 }
4673
4674 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", NULL);
4675
4676 if (!valid_socket)
4677 {
4678 _dbus_verbose ("launchd did not provide a socket path");
4679 _dbus_string_free(&socket_path);
4680 *supported = FALSE;
4681 return TRUE; /* Cannot use it, but not an error */
4682 }
4683 if (!_dbus_string_append (address, "unix:path="))
4684 {
4685 _DBUS_SET_OOM (error);
4686 _dbus_string_free(&socket_path);
4687 return FALSE;
4688 }
4689 if (!_dbus_string_copy (&socket_path, 0, address,
4690 _dbus_string_get_length (address)))
4691 {
4692 _DBUS_SET_OOM (error);
4693 _dbus_string_free(&socket_path);
4694 return FALSE;
4695 }
4696
4697 _dbus_string_free(&socket_path);
4698 return TRUE;
4699}
4700#endif
4701
4702static dbus_bool_t
4703_dbus_lookup_user_bus (dbus_bool_t *supported,
4704 DBusString *address,
4705 DBusError *error)
4706{
4707 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4708 dbus_bool_t ret = FALSE;
4709 struct stat stbuf;
4710 DBusString user_bus_path;
4711
4712 if (runtime_dir == NULL)
4713 {
4714 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4715 *supported = FALSE;
4716 return TRUE; /* Cannot use it, but not an error */
4717 }
4718
4719 if (!_dbus_string_init (&user_bus_path))
4720 {
4721 _DBUS_SET_OOM (error);
4722 return FALSE;
4723 }
4724
4725 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4726 {
4727 _DBUS_SET_OOM (error);
4728 goto out;
4729 }
4730
4731 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4732 {
4733 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4734 _dbus_strerror (errno));
4735 *supported = FALSE;
4736 ret = TRUE; /* Cannot use it, but not an error */
4737 goto out;
4738 }
4739
4740 if (stbuf.st_uid != getuid ())
4741 {
4742 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4743 (long) stbuf.st_uid, (long) getuid ());
4744 *supported = FALSE;
4745 ret = TRUE; /* Cannot use it, but not an error */
4746 goto out;
4747 }
4748
4749 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4750 {
4751 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4752 (long) stbuf.st_mode);
4753 *supported = FALSE;
4754 ret = TRUE; /* Cannot use it, but not an error */
4755 goto out;
4756 }
4757
4758 if (!_dbus_string_append (address, "unix:path=") ||
4759 !_dbus_address_append_escaped (address, &user_bus_path))
4760 {
4761 _DBUS_SET_OOM (error);
4762 goto out;
4763 }
4764
4765 *supported = TRUE;
4766 ret = TRUE;
4767
4768out:
4769 _dbus_string_free (&user_bus_path);
4770 return ret;
4771}
4772
4794 DBusString *address,
4795 DBusError *error)
4796{
4797#ifdef DBUS_ENABLE_LAUNCHD
4798 *supported = TRUE;
4799 return _dbus_lookup_session_address_launchd (supported, address, error);
4800#else
4801 *supported = FALSE;
4802
4803 if (!_dbus_lookup_user_bus (supported, address, error))
4804 return FALSE;
4805 else if (*supported)
4806 return TRUE;
4807
4808 /* On non-Mac Unix platforms, if the session address isn't already
4809 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4810 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4811 * autolaunch: global default; see init_session_address in
4812 * dbus/dbus-bus.c. */
4813 return TRUE;
4814#endif
4815}
4816
4824void
4829
4845 DBusCredentials *credentials)
4846{
4847 DBusString homedir;
4848 DBusString dotdir;
4849 dbus_uid_t uid;
4850
4851 _dbus_assert (credentials != NULL);
4853
4854 if (!_dbus_string_init (&homedir))
4855 return FALSE;
4856
4857 uid = _dbus_credentials_get_unix_uid (credentials);
4859
4860 if (!_dbus_homedir_from_uid (uid, &homedir))
4861 goto failed;
4862
4863#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4864 {
4865 const char *override;
4866
4867 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4868 if (override != NULL && *override != '\0')
4869 {
4870 _dbus_string_set_length (&homedir, 0);
4871 if (!_dbus_string_append (&homedir, override))
4872 goto failed;
4873
4874 _dbus_verbose ("Using fake homedir for testing: %s\n",
4875 _dbus_string_get_const_data (&homedir));
4876 }
4877 else
4878 {
4879 /* Not strictly thread-safe, but if we fail at thread-safety here,
4880 * the worst that will happen is some extra warnings. */
4881 static dbus_bool_t already_warned = FALSE;
4882 if (!already_warned)
4883 {
4884 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4885 _dbus_string_get_const_data (&homedir));
4886 already_warned = TRUE;
4887 }
4888 }
4889 }
4890#endif
4891
4892 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4893 if (!_dbus_concat_dir_and_file (&homedir,
4894 &dotdir))
4895 goto failed;
4896
4897 if (!_dbus_string_copy (&homedir, 0,
4898 directory, _dbus_string_get_length (directory))) {
4899 goto failed;
4900 }
4901
4902 _dbus_string_free (&homedir);
4903 return TRUE;
4904
4905 failed:
4906 _dbus_string_free (&homedir);
4907 return FALSE;
4908}
4909
4910/* Documented in dbus-sysdeps-win.c, does nothing on Unix */
4912_dbus_daemon_unpublish_session_bus_address (void)
4913{
4914 return TRUE;
4915}
4916
4925{
4926 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4927 * EWOULDBLOCK are numerically equal, which is permitted as described by
4928 * errno(3).
4929 */
4930#if EAGAIN == EWOULDBLOCK
4931 return e == EAGAIN;
4932#else
4933 return e == EAGAIN || e == EWOULDBLOCK;
4934#endif
4935}
4936
4946 DBusError *error)
4947{
4948 const char *filename_c;
4949
4950 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4951
4952 filename_c = _dbus_string_get_const_data (filename);
4953
4954 if (rmdir (filename_c) != 0)
4955 {
4957 "Failed to remove directory %s: %s\n",
4958 filename_c, _dbus_strerror (errno));
4959 return FALSE;
4960 }
4961
4962 return TRUE;
4963}
4964
4974{
4975#ifdef SCM_RIGHTS
4976 union {
4977 struct sockaddr sa;
4978 struct sockaddr_storage storage;
4979 struct sockaddr_un un;
4980 } sa_buf;
4981
4982 socklen_t sa_len = sizeof(sa_buf);
4983
4984 _DBUS_ZERO(sa_buf);
4985
4986 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4987 return FALSE;
4988
4989 return sa_buf.sa.sa_family == AF_UNIX;
4990
4991#else
4992 return FALSE;
4993
4994#endif
4995}
4996
4997/*
4998 * Similar to Solaris fdwalk(3), but without the ability to stop iteration,
4999 * and may call func for integers that are not actually valid fds.
5000 */
5001static void
5002act_on_fds_3_and_up (void (*func) (int fd))
5003{
5004 int maxfds, i;
5005
5006#if defined(__linux__) && defined(__GLIBC__)
5007 DIR *d;
5008
5009 /* On Linux we can optimize this a bit if /proc is available. If it
5010 isn't available, fall back to the brute force way. */
5011
5012 d = opendir ("/proc/self/fd");
5013 if (d)
5014 {
5015 for (;;)
5016 {
5017 struct dirent *de;
5018 int fd;
5019 long l;
5020 char *e = NULL;
5021
5022 de = readdir (d);
5023 if (!de)
5024 break;
5025
5026 if (de->d_name[0] == '.')
5027 continue;
5028
5029 errno = 0;
5030 l = strtol (de->d_name, &e, 10);
5031 if (errno != 0 || e == NULL || *e != '\0')
5032 continue;
5033
5034 fd = (int) l;
5035 if (fd < 3)
5036 continue;
5037
5038 if (fd == dirfd (d))
5039 continue;
5040
5041 func (fd);
5042 }
5043
5044 closedir (d);
5045 return;
5046 }
5047#endif
5048
5049 maxfds = sysconf (_SC_OPEN_MAX);
5050
5051 /* Pick something reasonable if for some reason sysconf says
5052 * unlimited.
5053 */
5054 if (maxfds < 0)
5055 maxfds = 1024;
5056
5057 /* close all inherited fds */
5058 for (i = 3; i < maxfds; i++)
5059 func (i);
5060}
5061
5062/* Some library implementations of closefrom() are not async-signal-safe,
5063 * and we call _dbus_close_all() after forking, so we only do this on
5064 * operating systems where we know that closefrom() is a system call */
5065#if defined(HAVE_CLOSEFROM) && ( \
5066 defined(__FreeBSD__) || \
5067 defined(__NetBSD__) || \
5068 defined(__OpenBSD__) || \
5069 defined(__sun__) && defined(F_CLOSEFROM) \
5070)
5071#define CLOSEFROM_SIGNAL_SAFE 1
5072#else
5073#define CLOSEFROM_SIGNAL_SAFE 0
5074static void
5075close_ignore_error (int fd)
5076{
5077 close (fd);
5078}
5079#endif
5080
5085void
5087{
5088#ifdef HAVE_CLOSE_RANGE
5089 if (close_range (3, INT_MAX, 0) == 0)
5090 return;
5091#endif
5092
5093#if CLOSEFROM_SIGNAL_SAFE
5094 closefrom (3);
5095#else
5096 act_on_fds_3_and_up (close_ignore_error);
5097#endif
5098}
5099
5104void
5106{
5107#if defined(HAVE_CLOSE_RANGE) && defined(CLOSE_RANGE_CLOEXEC)
5108 if (close_range (3, INT_MAX, CLOSE_RANGE_CLOEXEC) == 0)
5109 return;
5110#endif
5111
5112 act_on_fds_3_and_up (_dbus_fd_set_close_on_exec);
5113}
5114
5126{
5127 /* TODO: get __libc_enable_secure exported from glibc.
5128 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
5129 */
5130#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
5131 {
5132 /* See glibc/include/unistd.h */
5133 extern int __libc_enable_secure;
5134 return __libc_enable_secure;
5135 }
5136#elif defined(HAVE_ISSETUGID)
5137 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
5138 return issetugid ();
5139#else
5140 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
5141 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
5142
5143 /* We call into this function from _dbus_threads_init_platform_specific()
5144 * to make sure these are initialized before we start threading. */
5145 static dbus_bool_t check_setuid_initialised;
5146 static dbus_bool_t is_setuid;
5147
5148 if (_DBUS_UNLIKELY (!check_setuid_initialised))
5149 {
5150#ifdef HAVE_GETRESUID
5151 if (getresuid (&ruid, &euid, &suid) != 0 ||
5152 getresgid (&rgid, &egid, &sgid) != 0)
5153#endif /* HAVE_GETRESUID */
5154 {
5155 suid = ruid = getuid ();
5156 sgid = rgid = getgid ();
5157 euid = geteuid ();
5158 egid = getegid ();
5159 }
5160
5161 check_setuid_initialised = TRUE;
5162 is_setuid = (ruid != euid || ruid != suid ||
5163 rgid != egid || rgid != sgid);
5164
5165 }
5166 return is_setuid;
5167#endif
5168}
5169
5179 DBusString *address,
5180 DBusError *error)
5181{
5182 union {
5183 struct sockaddr sa;
5184 struct sockaddr_storage storage;
5185 struct sockaddr_un un;
5186 struct sockaddr_in ipv4;
5187 struct sockaddr_in6 ipv6;
5188 } socket;
5189 char hostip[INET6_ADDRSTRLEN];
5190 socklen_t size = sizeof (socket);
5191 DBusString path_str;
5192 const char *family_name = NULL;
5193 dbus_uint16_t port;
5194
5195 if (getsockname (fd.fd, &socket.sa, &size))
5196 goto err;
5197
5198 switch (socket.sa.sa_family)
5199 {
5200 case AF_UNIX:
5201 if (socket.un.sun_path[0]=='\0')
5202 {
5203 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
5204 if (_dbus_string_append (address, "unix:abstract=") &&
5205 _dbus_address_append_escaped (address, &path_str))
5206 {
5207 return TRUE;
5208 }
5209 else
5210 {
5211 _DBUS_SET_OOM (error);
5212 return FALSE;
5213 }
5214 }
5215 else
5216 {
5217 _dbus_string_init_const (&path_str, socket.un.sun_path);
5218 if (_dbus_string_append (address, "unix:path=") &&
5219 _dbus_address_append_escaped (address, &path_str))
5220 {
5221 return TRUE;
5222 }
5223 else
5224 {
5225 _DBUS_SET_OOM (error);
5226 return FALSE;
5227 }
5228 }
5229 /* not reached */
5230 break;
5231
5232 case AF_INET:
5233#ifdef AF_INET6
5234 case AF_INET6:
5235#endif
5236 _dbus_string_init_const (&path_str, hostip);
5237
5238 if (_dbus_inet_sockaddr_to_string (&socket, size, hostip, sizeof (hostip),
5239 &family_name, &port, error))
5240 {
5241 if (_dbus_string_append_printf (address, "tcp:family=%s,port=%u,host=",
5242 family_name, port) &&
5243 _dbus_address_append_escaped (address, &path_str))
5244 {
5245 return TRUE;
5246 }
5247 else
5248 {
5249 _DBUS_SET_OOM (error);
5250 return FALSE;
5251 }
5252 }
5253 else
5254 {
5255 return FALSE;
5256 }
5257 /* not reached */
5258 break;
5259
5260 default:
5261 dbus_set_error (error,
5262 _dbus_error_from_errno (EINVAL),
5263 "Failed to read address from socket: Unknown socket type.");
5264 return FALSE;
5265 }
5266 err:
5267 dbus_set_error (error,
5268 _dbus_error_from_errno (errno),
5269 "Failed to read address from socket: %s",
5270 _dbus_strerror (errno));
5271 return FALSE;
5272}
5273
5274int
5275_dbus_save_socket_errno (void)
5276{
5277 return errno;
5278}
5279
5280void
5281_dbus_restore_socket_errno (int saved_errno)
5282{
5283 errno = saved_errno;
5284}
5285
5286static const char *syslog_tag = "dbus";
5287#ifdef HAVE_SYSLOG_H
5288static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
5289#endif
5290
5305void
5306_dbus_init_system_log (const char *tag,
5307 DBusLogFlags flags)
5308{
5309 /* We never want to turn off logging completely */
5310 _dbus_assert (
5311 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
5312
5313 syslog_tag = tag;
5314
5315#ifdef HAVE_SYSLOG_H
5316 log_flags = flags;
5317
5318 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5319 openlog (tag, LOG_PID, LOG_DAEMON);
5320#endif
5321}
5322
5330void
5331_dbus_logv (DBusSystemLogSeverity severity,
5332 const char *msg,
5333 va_list args)
5334{
5335 va_list tmp;
5336#ifdef HAVE_SYSLOG_H
5337 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
5338 {
5339 int flags = LOG_DAEMON | LOG_WARNING;
5340 switch (severity)
5341 {
5342 case DBUS_SYSTEM_LOG_INFO:
5343 flags = LOG_DAEMON | LOG_INFO;
5344 break;
5345 case DBUS_SYSTEM_LOG_WARNING:
5346 flags = LOG_DAEMON | LOG_WARNING;
5347 break;
5348 case DBUS_SYSTEM_LOG_SECURITY:
5349 flags = LOG_AUTH | LOG_NOTICE;
5350 break;
5351 case DBUS_SYSTEM_LOG_ERROR:
5352 flags = LOG_DAEMON|LOG_CRIT;
5353 break;
5354 default:
5355 _dbus_assert_not_reached ("invalid log severity");
5356 }
5357
5358 va_copy (tmp, args);
5359 vsyslog (flags, msg, tmp);
5360 va_end (tmp);
5361 }
5362
5363 /* If we don't have syslog.h, we always behave as though stderr was in
5364 * the flags */
5365 if (log_flags & DBUS_LOG_FLAGS_STDERR)
5366#endif
5367 {
5368 va_copy (tmp, args);
5369 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
5370 vfprintf (stderr, msg, tmp);
5371 fputc ('\n', stderr);
5372 va_end (tmp);
5373 }
5374}
5375
5376/*
5377 * Return the low-level representation of a socket error, as used by
5378 * cross-platform socket APIs like inet_ntop(), send() and recv(). This
5379 * is the standard errno on Unix, but is WSAGetLastError() on Windows.
5380 *
5381 * Some libdbus internal functions copy this into errno, but with
5382 * hindsight that was probably a design flaw.
5383 */
5384int
5385_dbus_get_low_level_socket_errno (void)
5386{
5387 return errno;
5388}
5389
5390/* 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...
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_GNUC_NORETURN void _dbus_credentials_take_pid_fd(DBusCredentials *credentials, int pid_fd)
Add a UNIX process ID FD to the credentials.
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_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
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...
dbus_bool_t _dbus_file_get_contents(DBusString *str, const DBusString *filename, DBusError *error)
Appends the contents of the given file to the string, returning error code.
#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.
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;.
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.
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++.
Definition dbus-macros.h:51
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
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().
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
#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().
#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.
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
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...
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.
dbus_bool_t _dbus_string_find(const DBusString *str, int start, const char *substr, int *found)
Finds the given substring in the string, returning TRUE and filling in the byte index where the subst...
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_parse_uint(const DBusString *str, int start, unsigned long *value_return, int *end_return)
Parses an unsigned integer contained in a DBusString.
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
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.
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
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.
void _dbus_get_monotonic_time(dbus_int64_t *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
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.
unsigned long dbus_uid_t
A user ID.
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.
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.
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()).
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.
unsigned long dbus_gid_t
A group ID.
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
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
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_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...
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.
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).
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
dbus_pid_t _dbus_resolve_pid_fd(int pid_fd)
Resolve the PID from the PID FD, if any.
#define _DBUS_POLLNVAL
Invalid request: fd not open.
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.
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
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.
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
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_get_real_time(dbus_int64_t *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
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.
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
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.
unsigned short dbus_uint16_t
A 16-bit unsigned integer on all platforms.
_DBUS_GNUC_EXTENSION typedef long dbus_int64_t
A 64-bit signed integer.
int dbus_int32_t
A 32-bit signed integer on all platforms.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
An atomic integer safe to increment or decrement from multiple threads.
volatile dbus_int32_t value
Value of the atomic integer.
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.
short revents
Events that occurred.
DBusPollable fd
File descriptor.
Socket interface.
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...