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