D-Bus: dbus-sysdeps-unix.c Source File

D-Bus 1.14.10

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