D-Bus 1.12.2
dbus-sysdeps-unix.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3 *
4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26
27#include "dbus-internals.h"
28#include "dbus-sysdeps.h"
29#include "dbus-sysdeps-unix.h"
30#include "dbus-threads.h"
31#include "dbus-protocol.h"
32#include "dbus-file.h"
33#include "dbus-transport.h"
34#include "dbus-string.h"
35#include "dbus-userdb.h"
36#include "dbus-list.h"
37#include "dbus-credentials.h"
38#include "dbus-nonce.h"
39
40#include <sys/types.h>
41#include <stdlib.h>
42#include <string.h>
43#include <signal.h>
44#include <unistd.h>
45#include <stdio.h>
46#include <fcntl.h>
47#include <sys/socket.h>
48#include <dirent.h>
49#include <sys/un.h>
50#include <pwd.h>
51#include <time.h>
52#include <locale.h>
53#include <sys/time.h>
54#include <sys/stat.h>
55#include <sys/wait.h>
56#include <netinet/in.h>
57#include <netinet/tcp.h>
58#include <netdb.h>
59#include <grp.h>
60#include <arpa/inet.h>
61
62#ifdef HAVE_ERRNO_H
63#include <errno.h>
64#endif
65#ifdef HAVE_SYSLOG_H
66#include <syslog.h>
67#endif
68#ifdef HAVE_WRITEV
69#include <sys/uio.h>
70#endif
71#ifdef HAVE_POLL
72#include <sys/poll.h>
73#endif
74#ifdef HAVE_BACKTRACE
75#include <execinfo.h>
76#endif
77#ifdef HAVE_GETPEERUCRED
78#include <ucred.h>
79#endif
80#ifdef HAVE_ALLOCA_H
81#include <alloca.h>
82#endif
83
84#ifdef HAVE_ADT
85#include <bsm/adt.h>
86#endif
87
88#ifdef HAVE_SYSTEMD
89#include <systemd/sd-daemon.h>
90#endif
91
92#if !DBUS_USE_SYNC
93#include <pthread.h>
94#endif
95
96#ifndef O_BINARY
97#define O_BINARY 0
98#endif
99
100#ifndef AI_ADDRCONFIG
101#define AI_ADDRCONFIG 0
102#endif
103
104#ifndef HAVE_SOCKLEN_T
105#define socklen_t int
106#endif
107
108#if defined (__sun) || defined (__sun__)
109/*
110 * CMS_SPACE etc. definitions for Solaris < 10, based on
111 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
112 * via
113 * http://wiki.opencsw.org/porting-faq#toc10
114 *
115 * These are only redefined for Solaris, for now: if your OS needs these too,
116 * please file a bug. (Or preferably, improve your OS so they're not needed.)
117 */
118
119# ifndef CMSG_ALIGN
120# ifdef __sun__
121# define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
122# else
123 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
124# define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
125 ~(sizeof (long) - 1))
126# endif
127# endif
128
129# ifndef CMSG_SPACE
130# define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
131 CMSG_ALIGN (len))
132# endif
133
134# ifndef CMSG_LEN
135# define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
136# endif
137
138#endif /* Solaris */
139
155_dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
156 const char **error_str_p)
157{
158 static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
159 DBUS_FORCE_STDOUT_NULL,
160 DBUS_FORCE_STDERR_NULL };
161 /* Should always get replaced with the real error before use */
162 const char *error_str = "Failed mysteriously";
163 int devnull = -1;
164 int saved_errno;
165 /* This function relies on the standard fds having their POSIX values. */
166 _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
167 _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
168 _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
169 int i;
170
171 for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
172 {
173 /* Because we rely on being single-threaded, and we want the
174 * standard fds to not be close-on-exec, we don't set it
175 * close-on-exec. */
176 if (devnull < i)
177 devnull = open ("/dev/null", O_RDWR);
178
179 if (devnull < 0)
180 {
181 error_str = "Failed to open /dev/null";
182 goto out;
183 }
184
185 /* We already opened all fds < i, so the only way this assertion
186 * could fail is if another thread closed one, and we document
187 * this function as not safe for multi-threading. */
188 _dbus_assert (devnull >= i);
189
190 if (devnull != i && (flags & relevant_flag[i]) != 0)
191 {
192 if (dup2 (devnull, i) < 0)
193 {
194 error_str = "Failed to dup2 /dev/null onto a standard fd";
195 goto out;
196 }
197 }
198 }
199
200 error_str = NULL;
201
202out:
203 saved_errno = errno;
204
205 if (devnull > STDERR_FILENO)
206 close (devnull);
207
208 if (error_str_p != NULL)
209 *error_str_p = error_str;
210
211 errno = saved_errno;
212 return (error_str == NULL);
213}
214
215static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
216 DBusError *error);
217
218static dbus_bool_t
219_dbus_open_socket (int *fd_p,
220 int domain,
221 int type,
222 int protocol,
223 DBusError *error)
224{
225#ifdef SOCK_CLOEXEC
226 dbus_bool_t cloexec_done;
227
228 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
229 cloexec_done = *fd_p >= 0;
230
231 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
232 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
233#endif
234 {
235 *fd_p = socket (domain, type, protocol);
236 }
237
238 if (*fd_p >= 0)
239 {
240#ifdef SOCK_CLOEXEC
241 if (!cloexec_done)
242#endif
243 {
245 }
246
247 _dbus_verbose ("socket fd %d opened\n", *fd_p);
248 return TRUE;
249 }
250 else
251 {
252 dbus_set_error(error,
254 "Failed to open socket: %s",
255 _dbus_strerror (errno));
256 return FALSE;
257 }
258}
259
270static dbus_bool_t
271_dbus_open_unix_socket (int *fd,
272 DBusError *error)
273{
274 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
275}
276
287 DBusError *error)
288{
289 return _dbus_close (fd.fd, error);
290}
291
301int
303 DBusString *buffer,
304 int count)
305{
306 return _dbus_read (fd.fd, buffer, count);
307}
308
319int
321 const DBusString *buffer,
322 int start,
323 int len)
324{
325#if HAVE_DECL_MSG_NOSIGNAL
326 const char *data;
327 int bytes_written;
328
329 data = _dbus_string_get_const_data_len (buffer, start, len);
330
331 again:
332
333 bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
334
335 if (bytes_written < 0 && errno == EINTR)
336 goto again;
337
338 return bytes_written;
339
340#else
341 return _dbus_write (fd.fd, buffer, start, len);
342#endif
343}
344
357int
359 DBusString *buffer,
360 int count,
361 int *fds,
362 unsigned int *n_fds) {
363#ifndef HAVE_UNIX_FD_PASSING
364 int r;
365
366 if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
367 return r;
368
369 *n_fds = 0;
370 return r;
371
372#else
373 int bytes_read;
374 int start;
375 struct msghdr m;
376 struct iovec iov;
377
378 _dbus_assert (count >= 0);
380
381 start = _dbus_string_get_length (buffer);
382
383 if (!_dbus_string_lengthen (buffer, count))
384 {
385 errno = ENOMEM;
386 return -1;
387 }
388
389 _DBUS_ZERO(iov);
390 iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
391 iov.iov_len = count;
392
393 _DBUS_ZERO(m);
394 m.msg_iov = &iov;
395 m.msg_iovlen = 1;
396
397 /* Hmm, we have no clue how long the control data will actually be
398 that is queued for us. The least we can do is assume that the
399 caller knows. Hence let's make space for the number of fds that
400 we shall read at max plus the cmsg header. */
401 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
402
403 /* It's probably safe to assume that systems with SCM_RIGHTS also
404 know alloca() */
405 m.msg_control = alloca(m.msg_controllen);
406 memset(m.msg_control, 0, m.msg_controllen);
407
408 /* Do not include the padding at the end when we tell the kernel
409 * how much we're willing to receive. This avoids getting
410 * the padding filled with additional fds that we weren't expecting,
411 * if a (potentially malicious) sender included them. (fd.o #83622) */
412 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
413
414 again:
415
416 bytes_read = recvmsg (fd.fd, &m, 0
417#ifdef MSG_CMSG_CLOEXEC
418 |MSG_CMSG_CLOEXEC
419#endif
420 );
421
422 if (bytes_read < 0)
423 {
424 if (errno == EINTR)
425 goto again;
426 else
427 {
428 /* put length back (note that this doesn't actually realloc anything) */
429 _dbus_string_set_length (buffer, start);
430 return -1;
431 }
432 }
433 else
434 {
435 struct cmsghdr *cm;
436 dbus_bool_t found = FALSE;
437
438 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
439 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
440 {
441 size_t i;
442 int *payload = (int *) CMSG_DATA (cm);
443 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
444 size_t payload_len_fds = payload_len_bytes / sizeof (int);
445 size_t fds_to_use;
446
447 /* Every unsigned int fits in a size_t without truncation, so
448 * casting (size_t) *n_fds is OK */
449 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
450
451 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
452 {
453 /* The fds in the payload will fit in our buffer */
454 fds_to_use = payload_len_fds;
455 }
456 else
457 {
458 /* Too many fds in the payload. This shouldn't happen
459 * any more because we're setting m.msg_controllen to
460 * the exact number we can accept, but be safe and
461 * truncate. */
462 fds_to_use = (size_t) *n_fds;
463
464 /* Close the excess fds to avoid DoS: if they stayed open,
465 * someone could send us an extra fd per message
466 * and we'd eventually run out. */
467 for (i = fds_to_use; i < payload_len_fds; i++)
468 {
469 close (payload[i]);
470 }
471 }
472
473 memcpy (fds, payload, fds_to_use * sizeof (int));
474 found = TRUE;
475 /* This narrowing cast from size_t to unsigned int cannot
476 * overflow because we have chosen fds_to_use
477 * to be <= *n_fds */
478 *n_fds = (unsigned int) fds_to_use;
479
480 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
481 worked, hence we need to go through this list and set
482 CLOEXEC everywhere in any case */
483 for (i = 0; i < fds_to_use; i++)
485
486 break;
487 }
488
489 if (!found)
490 *n_fds = 0;
491
492 if (m.msg_flags & MSG_CTRUNC)
493 {
494 unsigned int i;
495
496 /* Hmm, apparently the control data was truncated. The bad
497 thing is that we might have completely lost a couple of fds
498 without chance to recover them. Hence let's treat this as a
499 serious error. */
500
501 /* We still need to close whatever fds we *did* receive,
502 * otherwise they'll never get closed. (CVE-2020-12049) */
503 for (i = 0; i < *n_fds; i++)
504 close (fds[i]);
505
506 *n_fds = 0;
507 errno = ENOSPC;
508 _dbus_string_set_length (buffer, start);
509 return -1;
510 }
511
512 /* put length back (doesn't actually realloc) */
513 _dbus_string_set_length (buffer, start + bytes_read);
514
515#if 0
516 if (bytes_read > 0)
517 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
518#endif
519
520 return bytes_read;
521 }
522#endif
523}
524
525int
526_dbus_write_socket_with_unix_fds(DBusSocket fd,
527 const DBusString *buffer,
528 int start,
529 int len,
530 const int *fds,
531 int n_fds) {
532
533#ifndef HAVE_UNIX_FD_PASSING
534
535 if (n_fds > 0) {
536 errno = ENOTSUP;
537 return -1;
538 }
539
540 return _dbus_write_socket(fd, buffer, start, len);
541#else
542 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
543#endif
544}
545
546int
547_dbus_write_socket_with_unix_fds_two(DBusSocket fd,
548 const DBusString *buffer1,
549 int start1,
550 int len1,
551 const DBusString *buffer2,
552 int start2,
553 int len2,
554 const int *fds,
555 int n_fds) {
556
557#ifndef HAVE_UNIX_FD_PASSING
558
559 if (n_fds > 0) {
560 errno = ENOTSUP;
561 return -1;
562 }
563
564 return _dbus_write_socket_two(fd,
565 buffer1, start1, len1,
566 buffer2, start2, len2);
567#else
568
569 struct msghdr m;
570 struct cmsghdr *cm;
571 struct iovec iov[2];
572 int bytes_written;
573
574 _dbus_assert (len1 >= 0);
575 _dbus_assert (len2 >= 0);
576 _dbus_assert (n_fds >= 0);
577
578 _DBUS_ZERO(iov);
579 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
580 iov[0].iov_len = len1;
581
582 if (buffer2)
583 {
584 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
585 iov[1].iov_len = len2;
586 }
587
588 _DBUS_ZERO(m);
589 m.msg_iov = iov;
590 m.msg_iovlen = buffer2 ? 2 : 1;
591
592 if (n_fds > 0)
593 {
594 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
595 m.msg_control = alloca(m.msg_controllen);
596 memset(m.msg_control, 0, m.msg_controllen);
597
598 cm = CMSG_FIRSTHDR(&m);
599 cm->cmsg_level = SOL_SOCKET;
600 cm->cmsg_type = SCM_RIGHTS;
601 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
602 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
603 }
604
605 again:
606
607 bytes_written = sendmsg (fd.fd, &m, 0
608#if HAVE_DECL_MSG_NOSIGNAL
609 |MSG_NOSIGNAL
610#endif
611 );
612
613 if (bytes_written < 0 && errno == EINTR)
614 goto again;
615
616#if 0
617 if (bytes_written > 0)
618 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
619#endif
620
621 return bytes_written;
622#endif
623}
624
638int
640 const DBusString *buffer1,
641 int start1,
642 int len1,
643 const DBusString *buffer2,
644 int start2,
645 int len2)
646{
647#if HAVE_DECL_MSG_NOSIGNAL
648 struct iovec vectors[2];
649 const char *data1;
650 const char *data2;
651 int bytes_written;
652 struct msghdr m;
653
654 _dbus_assert (buffer1 != NULL);
655 _dbus_assert (start1 >= 0);
656 _dbus_assert (start2 >= 0);
657 _dbus_assert (len1 >= 0);
658 _dbus_assert (len2 >= 0);
659
660 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
661
662 if (buffer2 != NULL)
663 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
664 else
665 {
666 data2 = NULL;
667 start2 = 0;
668 len2 = 0;
669 }
670
671 vectors[0].iov_base = (char*) data1;
672 vectors[0].iov_len = len1;
673 vectors[1].iov_base = (char*) data2;
674 vectors[1].iov_len = len2;
675
676 _DBUS_ZERO(m);
677 m.msg_iov = vectors;
678 m.msg_iovlen = data2 ? 2 : 1;
679
680 again:
681
682 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
683
684 if (bytes_written < 0 && errno == EINTR)
685 goto again;
686
687 return bytes_written;
688
689#else
690 return _dbus_write_two (fd.fd, buffer1, start1, len1,
691 buffer2, start2, len2);
692#endif
693}
694
711int
713 DBusString *buffer,
714 int count)
715{
716 int bytes_read;
717 int start;
718 char *data;
719
720 _dbus_assert (count >= 0);
721
722 start = _dbus_string_get_length (buffer);
723
724 if (!_dbus_string_lengthen (buffer, count))
725 {
726 errno = ENOMEM;
727 return -1;
728 }
729
730 data = _dbus_string_get_data_len (buffer, start, count);
731
732 again:
733
734 bytes_read = read (fd, data, count);
735
736 if (bytes_read < 0)
737 {
738 if (errno == EINTR)
739 goto again;
740 else
741 {
742 /* put length back (note that this doesn't actually realloc anything) */
743 _dbus_string_set_length (buffer, start);
744 return -1;
745 }
746 }
747 else
748 {
749 /* put length back (doesn't actually realloc) */
750 _dbus_string_set_length (buffer, start + bytes_read);
751
752#if 0
753 if (bytes_read > 0)
754 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
755#endif
756
757 return bytes_read;
758 }
759}
760
771int
773 const DBusString *buffer,
774 int start,
775 int len)
776{
777 const char *data;
778 int bytes_written;
779
780 data = _dbus_string_get_const_data_len (buffer, start, len);
781
782 again:
783
784 bytes_written = write (fd, data, len);
785
786 if (bytes_written < 0 && errno == EINTR)
787 goto again;
788
789#if 0
790 if (bytes_written > 0)
791 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
792#endif
793
794 return bytes_written;
795}
796
817int
819 const DBusString *buffer1,
820 int start1,
821 int len1,
822 const DBusString *buffer2,
823 int start2,
824 int len2)
825{
826 _dbus_assert (buffer1 != NULL);
827 _dbus_assert (start1 >= 0);
828 _dbus_assert (start2 >= 0);
829 _dbus_assert (len1 >= 0);
830 _dbus_assert (len2 >= 0);
831
832#ifdef HAVE_WRITEV
833 {
834 struct iovec vectors[2];
835 const char *data1;
836 const char *data2;
837 int bytes_written;
838
839 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
840
841 if (buffer2 != NULL)
842 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
843 else
844 {
845 data2 = NULL;
846 start2 = 0;
847 len2 = 0;
848 }
849
850 vectors[0].iov_base = (char*) data1;
851 vectors[0].iov_len = len1;
852 vectors[1].iov_base = (char*) data2;
853 vectors[1].iov_len = len2;
854
855 again:
856
857 bytes_written = writev (fd,
858 vectors,
859 data2 ? 2 : 1);
860
861 if (bytes_written < 0 && errno == EINTR)
862 goto again;
863
864 return bytes_written;
865 }
866#else /* HAVE_WRITEV */
867 {
868 int ret1, ret2;
869
870 ret1 = _dbus_write (fd, buffer1, start1, len1);
871 if (ret1 == len1 && buffer2 != NULL)
872 {
873 ret2 = _dbus_write (fd, buffer2, start2, len2);
874 if (ret2 < 0)
875 ret2 = 0; /* we can't report an error as the first write was OK */
876
877 return ret1 + ret2;
878 }
879 else
880 return ret1;
881 }
882#endif /* !HAVE_WRITEV */
883}
884
885#define _DBUS_MAX_SUN_PATH_LENGTH 99
886
916int
918 dbus_bool_t abstract,
919 DBusError *error)
920{
921 int fd;
922 size_t path_len;
923 struct sockaddr_un addr;
924
925 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
926
927 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
928 path, abstract);
929
930
931 if (!_dbus_open_unix_socket (&fd, error))
932 {
933 _DBUS_ASSERT_ERROR_IS_SET(error);
934 return -1;
935 }
936 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
937
938 _DBUS_ZERO (addr);
939 addr.sun_family = AF_UNIX;
940 path_len = strlen (path);
941
942 if (abstract)
943 {
944#ifdef __linux__
945 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
946 path_len++; /* Account for the extra nul byte added to the start of sun_path */
947
948 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
949 {
951 "Abstract socket name too long\n");
952 _dbus_close (fd, NULL);
953 return -1;
954 }
955
956 strncpy (&addr.sun_path[1], path, path_len);
957 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
958#else /* !__linux__ */
960 "Operating system does not support abstract socket namespace\n");
961 _dbus_close (fd, NULL);
962 return -1;
963#endif /* !__linux__ */
964 }
965 else
966 {
967 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
968 {
970 "Socket name too long\n");
971 _dbus_close (fd, NULL);
972 return -1;
973 }
974
975 strncpy (addr.sun_path, path, path_len);
976 }
977
978 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
979 {
980 dbus_set_error (error,
982 "Failed to connect to socket %s: %s",
983 path, _dbus_strerror (errno));
984
985 _dbus_close (fd, NULL);
986 return -1;
987 }
988
989 if (!_dbus_set_fd_nonblocking (fd, error))
990 {
991 _DBUS_ASSERT_ERROR_IS_SET (error);
992
993 _dbus_close (fd, NULL);
994 return -1;
995 }
996
997 return fd;
998}
999
1012int
1013_dbus_connect_exec (const char *path,
1014 char *const argv[],
1015 DBusError *error)
1016{
1017 int fds[2];
1018 pid_t pid;
1019 int retval;
1020 dbus_bool_t cloexec_done = 0;
1021
1022 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1023
1024 _dbus_verbose ("connecting to process %s\n", path);
1025
1026#ifdef SOCK_CLOEXEC
1027 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1028 cloexec_done = (retval >= 0);
1029
1030 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1031#endif
1032 {
1033 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1034 }
1035
1036 if (retval < 0)
1037 {
1038 dbus_set_error (error,
1039 _dbus_error_from_errno (errno),
1040 "Failed to create socket pair: %s",
1041 _dbus_strerror (errno));
1042 return -1;
1043 }
1044
1045 if (!cloexec_done)
1046 {
1049 }
1050
1051 pid = fork ();
1052 if (pid < 0)
1053 {
1054 dbus_set_error (error,
1055 _dbus_error_from_errno (errno),
1056 "Failed to fork() to call %s: %s",
1057 path, _dbus_strerror (errno));
1058 close (fds[0]);
1059 close (fds[1]);
1060 return -1;
1061 }
1062
1063 if (pid == 0)
1064 {
1065 /* child */
1066 close (fds[0]);
1067
1068 dup2 (fds[1], STDIN_FILENO);
1069 dup2 (fds[1], STDOUT_FILENO);
1070
1071 if (fds[1] != STDIN_FILENO &&
1072 fds[1] != STDOUT_FILENO)
1073 close (fds[1]);
1074
1075 /* Inherit STDERR and the controlling terminal from the
1076 parent */
1077
1078 _dbus_close_all ();
1079
1080 execvp (path, (char * const *) argv);
1081
1082 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1083
1084 _exit(1);
1085 }
1086
1087 /* parent */
1088 close (fds[1]);
1089
1090 if (!_dbus_set_fd_nonblocking (fds[0], error))
1091 {
1092 _DBUS_ASSERT_ERROR_IS_SET (error);
1093
1094 close (fds[0]);
1095 return -1;
1096 }
1097
1098 return fds[0];
1099}
1100
1118int
1120 dbus_bool_t abstract,
1121 DBusError *error)
1122{
1123 int listen_fd;
1124 struct sockaddr_un addr;
1125 size_t path_len;
1126
1127 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1128
1129 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1130 path, abstract);
1131
1132 if (!_dbus_open_unix_socket (&listen_fd, error))
1133 {
1134 _DBUS_ASSERT_ERROR_IS_SET(error);
1135 return -1;
1136 }
1137 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1138
1139 _DBUS_ZERO (addr);
1140 addr.sun_family = AF_UNIX;
1141 path_len = strlen (path);
1142
1143 if (abstract)
1144 {
1145#ifdef __linux__
1146 /* remember that abstract names aren't nul-terminated so we rely
1147 * on sun_path being filled in with zeroes above.
1148 */
1149 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1150 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1151
1152 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1153 {
1155 "Abstract socket name too long\n");
1156 _dbus_close (listen_fd, NULL);
1157 return -1;
1158 }
1159
1160 strncpy (&addr.sun_path[1], path, path_len);
1161 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1162#else /* !__linux__ */
1164 "Operating system does not support abstract socket namespace\n");
1165 _dbus_close (listen_fd, NULL);
1166 return -1;
1167#endif /* !__linux__ */
1168 }
1169 else
1170 {
1171 /* Discussed security implications of this with Nalin,
1172 * and we couldn't think of where it would kick our ass, but
1173 * it still seems a bit sucky. It also has non-security suckage;
1174 * really we'd prefer to exit if the socket is already in use.
1175 * But there doesn't seem to be a good way to do this.
1176 *
1177 * Just to be extra careful, I threw in the stat() - clearly
1178 * the stat() can't *fix* any security issue, but it at least
1179 * avoids inadvertent/accidental data loss.
1180 */
1181 {
1182 struct stat sb;
1183
1184 if (stat (path, &sb) == 0 &&
1185 S_ISSOCK (sb.st_mode))
1186 unlink (path);
1187 }
1188
1189 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1190 {
1192 "Socket name too long\n");
1193 _dbus_close (listen_fd, NULL);
1194 return -1;
1195 }
1196
1197 strncpy (addr.sun_path, path, path_len);
1198 }
1199
1200 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1201 {
1202 dbus_set_error (error, _dbus_error_from_errno (errno),
1203 "Failed to bind socket \"%s\": %s",
1204 path, _dbus_strerror (errno));
1205 _dbus_close (listen_fd, NULL);
1206 return -1;
1207 }
1208
1209 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1210 {
1211 dbus_set_error (error, _dbus_error_from_errno (errno),
1212 "Failed to listen on socket \"%s\": %s",
1213 path, _dbus_strerror (errno));
1214 _dbus_close (listen_fd, NULL);
1215 return -1;
1216 }
1217
1218 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1219 {
1220 _DBUS_ASSERT_ERROR_IS_SET (error);
1221 _dbus_close (listen_fd, NULL);
1222 return -1;
1223 }
1224
1225 /* Try opening up the permissions, but if we can't, just go ahead
1226 * and continue, maybe it will be good enough.
1227 */
1228 if (!abstract && chmod (path, 0777) < 0)
1229 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1230
1231 return listen_fd;
1232}
1233
1244int
1246 DBusError *error)
1247{
1248#ifdef HAVE_SYSTEMD
1249 int r, n;
1250 int fd;
1251 DBusSocket *new_fds;
1252
1253 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1254
1255 n = sd_listen_fds (TRUE);
1256 if (n < 0)
1257 {
1259 "Failed to acquire systemd socket: %s",
1260 _dbus_strerror (-n));
1261 return -1;
1262 }
1263
1264 if (n <= 0)
1265 {
1267 "No socket received.");
1268 return -1;
1269 }
1270
1271 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1272 {
1273 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1274 if (r < 0)
1275 {
1277 "Failed to verify systemd socket type: %s",
1278 _dbus_strerror (-r));
1279 return -1;
1280 }
1281
1282 if (!r)
1283 {
1285 "Passed socket has wrong type.");
1286 return -1;
1287 }
1288 }
1289
1290 /* OK, the file descriptors are all good, so let's take posession of
1291 them then. */
1292
1293 new_fds = dbus_new (DBusSocket, n);
1294 if (!new_fds)
1295 {
1297 "Failed to allocate file handle array.");
1298 goto fail;
1299 }
1300
1301 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1302 {
1303 if (!_dbus_set_fd_nonblocking (fd, error))
1304 {
1305 _DBUS_ASSERT_ERROR_IS_SET (error);
1306 goto fail;
1307 }
1308
1309 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1310 }
1311
1312 *fds = new_fds;
1313 return n;
1314
1315 fail:
1316
1317 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1318 {
1319 _dbus_close (fd, NULL);
1320 }
1321
1322 dbus_free (new_fds);
1323 return -1;
1324#else
1326 "dbus was compiled without systemd support");
1327 return -1;
1328#endif
1329}
1330
1346 const char *port,
1347 const char *family,
1348 DBusError *error)
1349{
1350 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1351}
1352
1354_dbus_connect_tcp_socket_with_nonce (const char *host,
1355 const char *port,
1356 const char *family,
1357 const char *noncefile,
1358 DBusError *error)
1359{
1360 int saved_errno = 0;
1361 DBusSocket fd = DBUS_SOCKET_INIT;
1362 int res;
1363 struct addrinfo hints;
1364 struct addrinfo *ai, *tmp;
1365
1366 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1367
1368 _DBUS_ZERO (hints);
1369
1370 if (!family)
1371 hints.ai_family = AF_UNSPEC;
1372 else if (!strcmp(family, "ipv4"))
1373 hints.ai_family = AF_INET;
1374 else if (!strcmp(family, "ipv6"))
1375 hints.ai_family = AF_INET6;
1376 else
1377 {
1378 dbus_set_error (error,
1380 "Unknown address family %s", family);
1381 return _dbus_socket_get_invalid ();
1382 }
1383 hints.ai_protocol = IPPROTO_TCP;
1384 hints.ai_socktype = SOCK_STREAM;
1385 hints.ai_flags = AI_ADDRCONFIG;
1386
1387 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1388 {
1389 dbus_set_error (error,
1390 _dbus_error_from_errno (errno),
1391 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1392 host, port, gai_strerror(res), res);
1393 return _dbus_socket_get_invalid ();
1394 }
1395
1396 tmp = ai;
1397 while (tmp)
1398 {
1399 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1400 {
1401 freeaddrinfo(ai);
1402 _DBUS_ASSERT_ERROR_IS_SET(error);
1403 return _dbus_socket_get_invalid ();
1404 }
1405 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1406
1407 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1408 {
1409 saved_errno = errno;
1410 _dbus_close (fd.fd, NULL);
1411 fd.fd = -1;
1412 tmp = tmp->ai_next;
1413 continue;
1414 }
1415
1416 break;
1417 }
1418 freeaddrinfo(ai);
1419
1420 if (fd.fd == -1)
1421 {
1422 dbus_set_error (error,
1423 _dbus_error_from_errno (saved_errno),
1424 "Failed to connect to socket \"%s:%s\" %s",
1425 host, port, _dbus_strerror(saved_errno));
1426 return _dbus_socket_get_invalid ();
1427 }
1428
1429 if (noncefile != NULL)
1430 {
1431 DBusString noncefileStr;
1432 dbus_bool_t ret;
1433 _dbus_string_init_const (&noncefileStr, noncefile);
1434 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1435 _dbus_string_free (&noncefileStr);
1436
1437 if (!ret)
1438 {
1439 _dbus_close (fd.fd, NULL);
1440 return _dbus_socket_get_invalid ();
1441 }
1442 }
1443
1444 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1445 {
1446 _dbus_close (fd.fd, NULL);
1447 return _dbus_socket_get_invalid ();
1448 }
1449
1450 return fd;
1451}
1452
1469int
1470_dbus_listen_tcp_socket (const char *host,
1471 const char *port,
1472 const char *family,
1473 DBusString *retport,
1474 DBusSocket **fds_p,
1475 DBusError *error)
1476{
1477 int saved_errno;
1478 int nlisten_fd = 0, res, i;
1479 DBusSocket *listen_fd = NULL;
1480 struct addrinfo hints;
1481 struct addrinfo *ai, *tmp;
1482 unsigned int reuseaddr;
1483
1484 *fds_p = NULL;
1485 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1486
1487 _DBUS_ZERO (hints);
1488
1489 if (!family)
1490 hints.ai_family = AF_UNSPEC;
1491 else if (!strcmp(family, "ipv4"))
1492 hints.ai_family = AF_INET;
1493 else if (!strcmp(family, "ipv6"))
1494 hints.ai_family = AF_INET6;
1495 else
1496 {
1497 dbus_set_error (error,
1499 "Unknown address family %s", family);
1500 return -1;
1501 }
1502
1503 hints.ai_protocol = IPPROTO_TCP;
1504 hints.ai_socktype = SOCK_STREAM;
1505 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1506
1507 redo_lookup_with_port:
1508 ai = NULL;
1509 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1510 {
1511 dbus_set_error (error,
1512 _dbus_error_from_errno (errno),
1513 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1514 host ? host : "*", port, gai_strerror(res), res);
1515 goto failed;
1516 }
1517
1518 tmp = ai;
1519 while (tmp)
1520 {
1521 int fd = -1, tcp_nodelay_on;
1522 DBusSocket *newlisten_fd;
1523
1524 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1525 {
1526 _DBUS_ASSERT_ERROR_IS_SET(error);
1527 goto failed;
1528 }
1529 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1530
1531 reuseaddr = 1;
1532 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1533 {
1534 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1535 host ? host : "*", port, _dbus_strerror (errno));
1536 }
1537
1538 /* Nagle's algorithm imposes a huge delay on the initial messages
1539 going over TCP. */
1540 tcp_nodelay_on = 1;
1541 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1542 {
1543 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1544 host ? host : "*", port, _dbus_strerror (errno));
1545 }
1546
1547 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1548 {
1549 saved_errno = errno;
1550 _dbus_close(fd, NULL);
1551 if (saved_errno == EADDRINUSE)
1552 {
1553 /* Depending on kernel policy, binding to an IPv6 address
1554 might implicitly bind to a corresponding IPv4
1555 address or vice versa, resulting in EADDRINUSE for the
1556 other one (e.g. bindv6only=0 on Linux).
1557
1558 Also, after we "goto redo_lookup_with_port" after binding
1559 a port on one of the possible addresses, we will
1560 try to bind that same port on every address, including the
1561 same address again for a second time; that one will
1562 also fail with EADDRINUSE.
1563
1564 For both those reasons, ignore EADDRINUSE here */
1565 tmp = tmp->ai_next;
1566 continue;
1567 }
1568 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1569 "Failed to bind socket \"%s:%s\": %s",
1570 host ? host : "*", port, _dbus_strerror (saved_errno));
1571 goto failed;
1572 }
1573
1574 if (listen (fd, 30 /* backlog */) < 0)
1575 {
1576 saved_errno = errno;
1577 _dbus_close (fd, NULL);
1578 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1579 "Failed to listen on socket \"%s:%s\": %s",
1580 host ? host : "*", port, _dbus_strerror (saved_errno));
1581 goto failed;
1582 }
1583
1584 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1585 if (!newlisten_fd)
1586 {
1587 saved_errno = errno;
1588 _dbus_close (fd, NULL);
1589 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1590 "Failed to allocate file handle array: %s",
1591 _dbus_strerror (saved_errno));
1592 goto failed;
1593 }
1594 listen_fd = newlisten_fd;
1595 listen_fd[nlisten_fd].fd = fd;
1596 nlisten_fd++;
1597
1598 if (!_dbus_string_get_length(retport))
1599 {
1600 /* If the user didn't specify a port, or used 0, then
1601 the kernel chooses a port. After the first address
1602 is bound to, we need to force all remaining addresses
1603 to use the same port */
1604 if (!port || !strcmp(port, "0"))
1605 {
1606 int result;
1607 struct sockaddr_storage addr;
1608 socklen_t addrlen;
1609 char portbuf[50];
1610
1611 addrlen = sizeof(addr);
1612 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1613
1614 if (result == -1 ||
1615 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1616 portbuf, sizeof(portbuf),
1617 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1618 {
1619 dbus_set_error (error, _dbus_error_from_errno (errno),
1620 "Failed to resolve port \"%s:%s\": %s (%d)",
1621 host ? host : "*", port, gai_strerror(res), res);
1622 goto failed;
1623 }
1624 if (!_dbus_string_append(retport, portbuf))
1625 {
1627 goto failed;
1628 }
1629
1630 /* Release current address list & redo lookup */
1631 port = _dbus_string_get_const_data(retport);
1632 freeaddrinfo(ai);
1633 goto redo_lookup_with_port;
1634 }
1635 else
1636 {
1637 if (!_dbus_string_append(retport, port))
1638 {
1640 goto failed;
1641 }
1642 }
1643 }
1644
1645 tmp = tmp->ai_next;
1646 }
1647 freeaddrinfo(ai);
1648 ai = NULL;
1649
1650 if (!nlisten_fd)
1651 {
1652 errno = EADDRINUSE;
1653 dbus_set_error (error, _dbus_error_from_errno (errno),
1654 "Failed to bind socket \"%s:%s\": %s",
1655 host ? host : "*", port, _dbus_strerror (errno));
1656 goto failed;
1657 }
1658
1659 for (i = 0 ; i < nlisten_fd ; i++)
1660 {
1661 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1662 {
1663 goto failed;
1664 }
1665 }
1666
1667 *fds_p = listen_fd;
1668
1669 return nlisten_fd;
1670
1671 failed:
1672 if (ai)
1673 freeaddrinfo(ai);
1674 for (i = 0 ; i < nlisten_fd ; i++)
1675 _dbus_close(listen_fd[i].fd, NULL);
1676 dbus_free(listen_fd);
1677 return -1;
1678}
1679
1680static dbus_bool_t
1681write_credentials_byte (int server_fd,
1682 DBusError *error)
1683{
1684 int bytes_written;
1685 char buf[1] = { '\0' };
1686#if defined(HAVE_CMSGCRED)
1687 union {
1688 struct cmsghdr hdr;
1689 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1690 } cmsg;
1691 struct iovec iov;
1692 struct msghdr msg;
1693 iov.iov_base = buf;
1694 iov.iov_len = 1;
1695
1696 _DBUS_ZERO(msg);
1697 msg.msg_iov = &iov;
1698 msg.msg_iovlen = 1;
1699
1700 msg.msg_control = (caddr_t) &cmsg;
1701 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1702 _DBUS_ZERO(cmsg);
1703 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1704 cmsg.hdr.cmsg_level = SOL_SOCKET;
1705 cmsg.hdr.cmsg_type = SCM_CREDS;
1706#endif
1707
1708 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1709
1710 again:
1711
1712#if defined(HAVE_CMSGCRED)
1713 bytes_written = sendmsg (server_fd, &msg, 0
1714#if HAVE_DECL_MSG_NOSIGNAL
1715 |MSG_NOSIGNAL
1716#endif
1717 );
1718
1719 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1720 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1721 * only allows that on AF_UNIX. Try just doing a send() instead. */
1722 if (bytes_written < 0 && errno == EINVAL)
1723#endif
1724 {
1725 bytes_written = send (server_fd, buf, 1, 0
1726#if HAVE_DECL_MSG_NOSIGNAL
1727 |MSG_NOSIGNAL
1728#endif
1729 );
1730 }
1731
1732 if (bytes_written < 0 && errno == EINTR)
1733 goto again;
1734
1735 if (bytes_written < 0)
1736 {
1737 dbus_set_error (error, _dbus_error_from_errno (errno),
1738 "Failed to write credentials byte: %s",
1739 _dbus_strerror (errno));
1740 return FALSE;
1741 }
1742 else if (bytes_written == 0)
1743 {
1745 "wrote zero bytes writing credentials byte");
1746 return FALSE;
1747 }
1748 else
1749 {
1750 _dbus_assert (bytes_written == 1);
1751 _dbus_verbose ("wrote credentials byte\n");
1752 return TRUE;
1753 }
1754}
1755
1756/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1757static dbus_bool_t
1758add_linux_security_label_to_credentials (int client_fd,
1759 DBusCredentials *credentials)
1760{
1761#if defined(__linux__) && defined(SO_PEERSEC)
1762 DBusString buf;
1763 socklen_t len = 1024;
1764 dbus_bool_t oom = FALSE;
1765
1766 if (!_dbus_string_init_preallocated (&buf, len) ||
1767 !_dbus_string_set_length (&buf, len))
1768 return FALSE;
1769
1770 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1771 _dbus_string_get_data (&buf), &len) < 0)
1772 {
1773 int e = errno;
1774
1775 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1776 _dbus_strerror (e), (unsigned long) len);
1777
1778 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1779 {
1780 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1781 _dbus_strerror (e));
1782 goto out;
1783 }
1784
1785 /* If not enough space, len is updated to be enough.
1786 * Try again with a large enough buffer. */
1787 if (!_dbus_string_set_length (&buf, len))
1788 {
1789 oom = TRUE;
1790 goto out;
1791 }
1792
1793 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1794 }
1795
1796 if (len <= 0)
1797 {
1798 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1799 (unsigned long) len);
1800 goto out;
1801 }
1802
1803 if (len > _dbus_string_get_length_uint (&buf))
1804 {
1805 _dbus_verbose ("%lu > %u", (unsigned long) len,
1806 _dbus_string_get_length_uint (&buf));
1807 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1808 }
1809
1810 if (_dbus_string_get_byte (&buf, len - 1) == 0)
1811 {
1812 /* the kernel included the trailing \0 in its count,
1813 * but DBusString always has an extra \0 after the data anyway */
1814 _dbus_verbose ("subtracting trailing \\0\n");
1815 len--;
1816 }
1817
1818 if (!_dbus_string_set_length (&buf, len))
1819 {
1820 _dbus_assert_not_reached ("shortening string should not lead to OOM");
1821 oom = TRUE;
1822 goto out;
1823 }
1824
1825 if (strlen (_dbus_string_get_const_data (&buf)) != len)
1826 {
1827 /* LSM people on the linux-security-module@ mailing list say this
1828 * should never happen: the label should be a bytestring with
1829 * an optional trailing \0 */
1830 _dbus_verbose ("security label from kernel had an embedded \\0, "
1831 "ignoring it\n");
1832 goto out;
1833 }
1834
1835 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1836 (unsigned long) len,
1837 _dbus_string_get_const_data (&buf));
1838
1840 _dbus_string_get_const_data (&buf)))
1841 {
1842 oom = TRUE;
1843 goto out;
1844 }
1845
1846out:
1847 _dbus_string_free (&buf);
1848 return !oom;
1849#else
1850 /* no error */
1851 return TRUE;
1852#endif
1853}
1854
1897 DBusCredentials *credentials,
1898 DBusError *error)
1899{
1900 struct msghdr msg;
1901 struct iovec iov;
1902 char buf;
1903 dbus_uid_t uid_read;
1904 dbus_pid_t pid_read;
1905 int bytes_read;
1906
1907#ifdef HAVE_CMSGCRED
1908 union {
1909 struct cmsghdr hdr;
1910 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1911 } cmsg;
1912#endif
1913
1914 /* The POSIX spec certainly doesn't promise this, but
1915 * we need these assertions to fail as soon as we're wrong about
1916 * it so we can do the porting fixups
1917 */
1918 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1919 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1920 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1921
1922 uid_read = DBUS_UID_UNSET;
1923 pid_read = DBUS_PID_UNSET;
1924
1925 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1926
1927 _dbus_credentials_clear (credentials);
1928
1929 iov.iov_base = &buf;
1930 iov.iov_len = 1;
1931
1932 _DBUS_ZERO(msg);
1933 msg.msg_iov = &iov;
1934 msg.msg_iovlen = 1;
1935
1936#if defined(HAVE_CMSGCRED)
1937 _DBUS_ZERO(cmsg);
1938 msg.msg_control = (caddr_t) &cmsg;
1939 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1940#endif
1941
1942 again:
1943 bytes_read = recvmsg (client_fd.fd, &msg, 0);
1944
1945 if (bytes_read < 0)
1946 {
1947 if (errno == EINTR)
1948 goto again;
1949
1950 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1951 * normally only call read_credentials if the socket was ready
1952 * for reading
1953 */
1954
1955 dbus_set_error (error, _dbus_error_from_errno (errno),
1956 "Failed to read credentials byte: %s",
1957 _dbus_strerror (errno));
1958 return FALSE;
1959 }
1960 else if (bytes_read == 0)
1961 {
1962 /* this should not happen unless we are using recvmsg wrong,
1963 * so is essentially here for paranoia
1964 */
1966 "Failed to read credentials byte (zero-length read)");
1967 return FALSE;
1968 }
1969 else if (buf != '\0')
1970 {
1972 "Credentials byte was not nul");
1973 return FALSE;
1974 }
1975
1976 _dbus_verbose ("read credentials byte\n");
1977
1978 {
1979#ifdef SO_PEERCRED
1980 /* Supported by at least Linux and OpenBSD, with minor differences.
1981 *
1982 * This mechanism passes the process ID through and does not require
1983 * the peer's cooperation, so we prefer it over all others. Notably,
1984 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
1985 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
1986 * because this is much less fragile.
1987 */
1988#ifdef __OpenBSD__
1989 struct sockpeercred cr;
1990#else
1991 struct ucred cr;
1992#endif
1993 socklen_t cr_len = sizeof (cr);
1994
1995 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
1996 {
1997 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
1998 _dbus_strerror (errno));
1999 }
2000 else if (cr_len != sizeof (cr))
2001 {
2002 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2003 cr_len, (int) sizeof (cr));
2004 }
2005 else
2006 {
2007 pid_read = cr.pid;
2008 uid_read = cr.uid;
2009 }
2010#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2011 /* Another variant of the above - used on NetBSD
2012 */
2013 struct unpcbid cr;
2014 socklen_t cr_len = sizeof (cr);
2015
2016 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2017 {
2018 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2019 _dbus_strerror (errno));
2020 }
2021 else if (cr_len != sizeof (cr))
2022 {
2023 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2024 cr_len, (int) sizeof (cr));
2025 }
2026 else
2027 {
2028 pid_read = cr.unp_pid;
2029 uid_read = cr.unp_euid;
2030 }
2031#elif defined(HAVE_CMSGCRED)
2032 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2033 * presence of that struct implies SCM_CREDS. Supported by at least
2034 * FreeBSD and DragonflyBSD.
2035 *
2036 * This mechanism requires the peer to help us (it has to send us a
2037 * SCM_CREDS message) but it does pass the process ID through,
2038 * which makes it better than getpeereid().
2039 */
2040 struct cmsgcred *cred;
2041 struct cmsghdr *cmsgp;
2042
2043 for (cmsgp = CMSG_FIRSTHDR (&msg);
2044 cmsgp != NULL;
2045 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2046 {
2047 if (cmsgp->cmsg_type == SCM_CREDS &&
2048 cmsgp->cmsg_level == SOL_SOCKET &&
2049 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2050 {
2051 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2052 pid_read = cred->cmcred_pid;
2053 uid_read = cred->cmcred_euid;
2054 break;
2055 }
2056 }
2057
2058#elif defined(HAVE_GETPEERUCRED)
2059 /* Supported in at least Solaris >= 10. It should probably be higher
2060 * up this list, because it carries the pid and we use this code path
2061 * for audit data. */
2062 ucred_t * ucred = NULL;
2063 if (getpeerucred (client_fd.fd, &ucred) == 0)
2064 {
2065#ifdef HAVE_ADT
2066 adt_session_data_t *adth = NULL;
2067#endif
2068 pid_read = ucred_getpid (ucred);
2069 uid_read = ucred_geteuid (ucred);
2070#ifdef HAVE_ADT
2071 /* generate audit session data based on socket ucred */
2072 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2073 {
2074 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2075 }
2076 else
2077 {
2078 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2079 {
2080 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2081 }
2082 else
2083 {
2084 adt_export_data_t *data = NULL;
2085 size_t size = adt_export_session_data (adth, &data);
2086 if (size <= 0)
2087 {
2088 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2089 }
2090 else
2091 {
2092 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2093 free (data);
2094 }
2095 }
2096 (void) adt_end_session (adth);
2097 }
2098#endif /* HAVE_ADT */
2099 }
2100 else
2101 {
2102 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2103 }
2104 if (ucred != NULL)
2105 ucred_free (ucred);
2106
2107 /* ----------------------------------------------------------------
2108 * When adding new mechanisms, please add them above this point
2109 * if they support passing the process ID through, or below if not.
2110 * ---------------------------------------------------------------- */
2111
2112#elif defined(HAVE_GETPEEREID)
2113 /* getpeereid() originates from D.J. Bernstein and is fairly
2114 * widely-supported. According to a web search, it might be present in
2115 * any/all of:
2116 *
2117 * - AIX?
2118 * - Blackberry?
2119 * - Cygwin
2120 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2121 * - Mac OS X
2122 * - Minix 3.1.8+
2123 * - MirBSD?
2124 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2125 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2126 * - QNX?
2127 */
2128 uid_t euid;
2129 gid_t egid;
2130 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2131 {
2132 uid_read = euid;
2133 }
2134 else
2135 {
2136 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2137 }
2138#else /* no supported mechanism */
2139
2140#warning Socket credentials not supported on this Unix OS
2141#warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2142
2143 /* Please add other operating systems known to support at least one of
2144 * the mechanisms above to this list, keeping alphabetical order.
2145 * Everything not in this list is best-effort.
2146 */
2147#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2148 defined(__linux__) || \
2149 defined(__OpenBSD__) || \
2150 defined(__NetBSD__)
2151# error Credentials passing not working on this OS is a regression!
2152#endif
2153
2154 _dbus_verbose ("Socket credentials not supported on this OS\n");
2155#endif
2156 }
2157
2158 _dbus_verbose ("Credentials:"
2159 " pid "DBUS_PID_FORMAT
2160 " uid "DBUS_UID_FORMAT
2161 "\n",
2162 pid_read,
2163 uid_read);
2164
2165 if (pid_read != DBUS_PID_UNSET)
2166 {
2167 if (!_dbus_credentials_add_pid (credentials, pid_read))
2168 {
2169 _DBUS_SET_OOM (error);
2170 return FALSE;
2171 }
2172 }
2173
2174 if (uid_read != DBUS_UID_UNSET)
2175 {
2176 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2177 {
2178 _DBUS_SET_OOM (error);
2179 return FALSE;
2180 }
2181 }
2182
2183 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2184 {
2185 _DBUS_SET_OOM (error);
2186 return FALSE;
2187 }
2188
2189 return TRUE;
2190}
2191
2211 DBusError *error)
2212{
2213 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2214
2215 if (write_credentials_byte (server_fd.fd, error))
2216 return TRUE;
2217 else
2218 return FALSE;
2219}
2220
2232{
2233 DBusSocket client_fd;
2234 struct sockaddr addr;
2235 socklen_t addrlen;
2236#ifdef HAVE_ACCEPT4
2237 dbus_bool_t cloexec_done;
2238#endif
2239
2240 addrlen = sizeof (addr);
2241
2242 retry:
2243
2244#ifdef HAVE_ACCEPT4
2245 /*
2246 * At compile-time, we assume that if accept4() is available in
2247 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2248 * not necessarily true that either is supported by the running kernel.
2249 */
2250 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2251 cloexec_done = client_fd.fd >= 0;
2252
2253 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2254#endif
2255 {
2256 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2257 }
2258
2259 if (client_fd.fd < 0)
2260 {
2261 if (errno == EINTR)
2262 goto retry;
2263 }
2264
2265 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2266
2267#ifdef HAVE_ACCEPT4
2268 if (!cloexec_done)
2269#endif
2270 {
2271 _dbus_fd_set_close_on_exec(client_fd.fd);
2272 }
2273
2274 return client_fd;
2275}
2276
2287{
2288 const char *directory;
2289 struct stat sb;
2290
2291 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2292
2293 directory = _dbus_string_get_const_data (dir);
2294
2295 if (stat (directory, &sb) < 0)
2296 {
2297 dbus_set_error (error, _dbus_error_from_errno (errno),
2298 "%s", _dbus_strerror (errno));
2299
2300 return FALSE;
2301 }
2302
2303 if (sb.st_uid != geteuid ())
2304 {
2306 "%s directory is owned by user %lu, not %lu",
2307 directory,
2308 (unsigned long) sb.st_uid,
2309 (unsigned long) geteuid ());
2310 return FALSE;
2311 }
2312
2313 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2314 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2315 {
2317 "%s directory is not private to the user", directory);
2318 return FALSE;
2319 }
2320
2321 return TRUE;
2322}
2323
2324static dbus_bool_t
2325fill_user_info_from_passwd (struct passwd *p,
2326 DBusUserInfo *info,
2327 DBusError *error)
2328{
2329 _dbus_assert (p->pw_name != NULL);
2330 _dbus_assert (p->pw_dir != NULL);
2331
2332 info->uid = p->pw_uid;
2333 info->primary_gid = p->pw_gid;
2334 info->username = _dbus_strdup (p->pw_name);
2335 info->homedir = _dbus_strdup (p->pw_dir);
2336
2337 if (info->username == NULL ||
2338 info->homedir == NULL)
2339 {
2341 return FALSE;
2342 }
2343
2344 return TRUE;
2345}
2346
2347static dbus_bool_t
2348fill_user_info (DBusUserInfo *info,
2349 dbus_uid_t uid,
2350 const DBusString *username,
2351 DBusError *error)
2352{
2353 const char *username_c;
2354
2355 /* exactly one of username/uid provided */
2356 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2357 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2358
2359 info->uid = DBUS_UID_UNSET;
2361 info->group_ids = NULL;
2362 info->n_group_ids = 0;
2363 info->username = NULL;
2364 info->homedir = NULL;
2365
2366 if (username != NULL)
2367 username_c = _dbus_string_get_const_data (username);
2368 else
2369 username_c = NULL;
2370
2371 /* For now assuming that the getpwnam() and getpwuid() flavors
2372 * are always symmetrical, if not we have to add more configure
2373 * checks
2374 */
2375
2376#if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2377 {
2378 struct passwd *p;
2379 int result;
2380 size_t buflen;
2381 char *buf;
2382 struct passwd p_str;
2383
2384 /* retrieve maximum needed size for buf */
2385 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2386
2387 /* sysconf actually returns a long, but everything else expects size_t,
2388 * so just recast here.
2389 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2390 */
2391 if ((long) buflen <= 0)
2392 buflen = 1024;
2393
2394 result = -1;
2395 while (1)
2396 {
2397 buf = dbus_malloc (buflen);
2398 if (buf == NULL)
2399 {
2401 return FALSE;
2402 }
2403
2404 p = NULL;
2405#ifdef HAVE_POSIX_GETPWNAM_R
2406 if (uid != DBUS_UID_UNSET)
2407 result = getpwuid_r (uid, &p_str, buf, buflen,
2408 &p);
2409 else
2410 result = getpwnam_r (username_c, &p_str, buf, buflen,
2411 &p);
2412#else
2413 if (uid != DBUS_UID_UNSET)
2414 p = getpwuid_r (uid, &p_str, buf, buflen);
2415 else
2416 p = getpwnam_r (username_c, &p_str, buf, buflen);
2417 result = 0;
2418#endif /* !HAVE_POSIX_GETPWNAM_R */
2419 //Try a bigger buffer if ERANGE was returned
2420 if (result == ERANGE && buflen < 512 * 1024)
2421 {
2422 dbus_free (buf);
2423 buflen *= 2;
2424 }
2425 else
2426 {
2427 break;
2428 }
2429 }
2430 if (result == 0 && p == &p_str)
2431 {
2432 if (!fill_user_info_from_passwd (p, info, error))
2433 {
2434 dbus_free (buf);
2435 return FALSE;
2436 }
2437 dbus_free (buf);
2438 }
2439 else
2440 {
2441 dbus_set_error (error, _dbus_error_from_errno (errno),
2442 "User \"%s\" unknown or no memory to allocate password entry\n",
2443 username_c ? username_c : "???");
2444 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2445 dbus_free (buf);
2446 return FALSE;
2447 }
2448 }
2449#else /* ! HAVE_GETPWNAM_R */
2450 {
2451 /* I guess we're screwed on thread safety here */
2452 struct passwd *p;
2453
2454 if (uid != DBUS_UID_UNSET)
2455 p = getpwuid (uid);
2456 else
2457 p = getpwnam (username_c);
2458
2459 if (p != NULL)
2460 {
2461 if (!fill_user_info_from_passwd (p, info, error))
2462 {
2463 return FALSE;
2464 }
2465 }
2466 else
2467 {
2468 dbus_set_error (error, _dbus_error_from_errno (errno),
2469 "User \"%s\" unknown or no memory to allocate password entry\n",
2470 username_c ? username_c : "???");
2471 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2472 return FALSE;
2473 }
2474 }
2475#endif /* ! HAVE_GETPWNAM_R */
2476
2477 /* Fill this in so we can use it to get groups */
2478 username_c = info->username;
2479
2480#ifdef HAVE_GETGROUPLIST
2481 {
2482 gid_t *buf;
2483 int buf_count;
2484 int i;
2485 int initial_buf_count;
2486
2487 initial_buf_count = 17;
2488 buf_count = initial_buf_count;
2489 buf = dbus_new (gid_t, buf_count);
2490 if (buf == NULL)
2491 {
2493 goto failed;
2494 }
2495
2496 if (getgrouplist (username_c,
2497 info->primary_gid,
2498 buf, &buf_count) < 0)
2499 {
2500 gid_t *new;
2501 /* Presumed cause of negative return code: buf has insufficient
2502 entries to hold the entire group list. The Linux behavior in this
2503 case is to pass back the actual number of groups in buf_count, but
2504 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2505 So as a hack, try to help out a bit by guessing a larger
2506 number of groups, within reason.. might still fail, of course,
2507 but we can at least print a more informative message. I looked up
2508 the "right way" to do this by downloading Apple's own source code
2509 for the "id" command, and it turns out that they use an
2510 undocumented library function getgrouplist_2 (!) which is not
2511 declared in any header in /usr/include (!!). That did not seem
2512 like the way to go here.
2513 */
2514 if (buf_count == initial_buf_count)
2515 {
2516 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2517 }
2518 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2519 if (new == NULL)
2520 {
2522 dbus_free (buf);
2523 goto failed;
2524 }
2525
2526 buf = new;
2527
2528 errno = 0;
2529 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2530 {
2531 if (errno == 0)
2532 {
2533 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2534 username_c, buf_count, buf_count);
2535 }
2536 else
2537 {
2538 dbus_set_error (error,
2539 _dbus_error_from_errno (errno),
2540 "Failed to get groups for username \"%s\" primary GID "
2541 DBUS_GID_FORMAT ": %s\n",
2542 username_c, info->primary_gid,
2543 _dbus_strerror (errno));
2544 dbus_free (buf);
2545 goto failed;
2546 }
2547 }
2548 }
2549
2550 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2551 if (info->group_ids == NULL)
2552 {
2554 dbus_free (buf);
2555 goto failed;
2556 }
2557
2558 for (i = 0; i < buf_count; ++i)
2559 info->group_ids[i] = buf[i];
2560
2561 info->n_group_ids = buf_count;
2562
2563 dbus_free (buf);
2564 }
2565#else /* HAVE_GETGROUPLIST */
2566 {
2567 /* We just get the one group ID */
2568 info->group_ids = dbus_new (dbus_gid_t, 1);
2569 if (info->group_ids == NULL)
2570 {
2572 goto failed;
2573 }
2574
2575 info->n_group_ids = 1;
2576
2577 (info->group_ids)[0] = info->primary_gid;
2578 }
2579#endif /* HAVE_GETGROUPLIST */
2580
2581 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2582
2583 return TRUE;
2584
2585 failed:
2586 _DBUS_ASSERT_ERROR_IS_SET (error);
2587 return FALSE;
2588}
2589
2600 const DBusString *username,
2601 DBusError *error)
2602{
2603 return fill_user_info (info, DBUS_UID_UNSET,
2604 username, error);
2605}
2606
2617 dbus_uid_t uid,
2618 DBusError *error)
2619{
2620 return fill_user_info (info, uid,
2621 NULL, error);
2622}
2623
2633{
2634 /* The POSIX spec certainly doesn't promise this, but
2635 * we need these assertions to fail as soon as we're wrong about
2636 * it so we can do the porting fixups
2637 */
2638 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2639 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2640 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2641
2642 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2643 return FALSE;
2644 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2645 return FALSE;
2646
2647 return TRUE;
2648}
2649
2667
2674{
2675 return getpid ();
2676}
2677
2683{
2684 return getuid ();
2685}
2686
2692{
2693 return geteuid ();
2694}
2695
2702unsigned long
2704{
2705 return getpid ();
2706}
2707
2717 dbus_uid_t *uid)
2718{
2719 int end;
2720 long val;
2721
2722 if (_dbus_string_get_length (uid_str) == 0)
2723 {
2724 _dbus_verbose ("UID string was zero length\n");
2725 return FALSE;
2726 }
2727
2728 val = -1;
2729 end = 0;
2730 if (!_dbus_string_parse_int (uid_str, 0, &val,
2731 &end))
2732 {
2733 _dbus_verbose ("could not parse string as a UID\n");
2734 return FALSE;
2735 }
2736
2737 if (end != _dbus_string_get_length (uid_str))
2738 {
2739 _dbus_verbose ("string contained trailing stuff after UID\n");
2740 return FALSE;
2741 }
2742
2743 *uid = val;
2744
2745 return TRUE;
2746}
2747
2748#if !DBUS_USE_SYNC
2749/* To be thread-safe by default on platforms that don't necessarily have
2750 * atomic operations (notably Debian armel, which is armv4t), we must
2751 * use a mutex that can be initialized statically, like this.
2752 * GLib >= 2.32 uses a similar system.
2753 */
2754static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2755#endif
2756
2765{
2766#if DBUS_USE_SYNC
2767 return __sync_add_and_fetch(&atomic->value, 1)-1;
2768#else
2769 dbus_int32_t res;
2770
2771 pthread_mutex_lock (&atomic_mutex);
2772 res = atomic->value;
2773 atomic->value += 1;
2774 pthread_mutex_unlock (&atomic_mutex);
2775
2776 return res;
2777#endif
2778}
2779
2788{
2789#if DBUS_USE_SYNC
2790 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2791#else
2792 dbus_int32_t res;
2793
2794 pthread_mutex_lock (&atomic_mutex);
2795 res = atomic->value;
2796 atomic->value -= 1;
2797 pthread_mutex_unlock (&atomic_mutex);
2798
2799 return res;
2800#endif
2801}
2802
2812{
2813#if DBUS_USE_SYNC
2814 __sync_synchronize ();
2815 return atomic->value;
2816#else
2817 dbus_int32_t res;
2818
2819 pthread_mutex_lock (&atomic_mutex);
2820 res = atomic->value;
2821 pthread_mutex_unlock (&atomic_mutex);
2822
2823 return res;
2824#endif
2825}
2826
2835int
2837 int n_fds,
2838 int timeout_milliseconds)
2839{
2840#if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2841 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2842 if (timeout_milliseconds < -1)
2843 {
2844 timeout_milliseconds = -1;
2845 }
2846
2847 return poll (fds,
2848 n_fds,
2849 timeout_milliseconds);
2850#else /* ! HAVE_POLL */
2851 /* Emulate poll() in terms of select() */
2852 fd_set read_set, write_set, err_set;
2853 int max_fd = 0;
2854 int i;
2855 struct timeval tv;
2856 int ready;
2857
2858 FD_ZERO (&read_set);
2859 FD_ZERO (&write_set);
2860 FD_ZERO (&err_set);
2861
2862 for (i = 0; i < n_fds; i++)
2863 {
2864 DBusPollFD *fdp = &fds[i];
2865
2866 if (fdp->events & _DBUS_POLLIN)
2867 FD_SET (fdp->fd, &read_set);
2868
2869 if (fdp->events & _DBUS_POLLOUT)
2870 FD_SET (fdp->fd, &write_set);
2871
2872 FD_SET (fdp->fd, &err_set);
2873
2874 max_fd = MAX (max_fd, fdp->fd);
2875 }
2876
2877 tv.tv_sec = timeout_milliseconds / 1000;
2878 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2879
2880 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2881 timeout_milliseconds < 0 ? NULL : &tv);
2882
2883 if (ready > 0)
2884 {
2885 for (i = 0; i < n_fds; i++)
2886 {
2887 DBusPollFD *fdp = &fds[i];
2888
2889 fdp->revents = 0;
2890
2891 if (FD_ISSET (fdp->fd, &read_set))
2892 fdp->revents |= _DBUS_POLLIN;
2893
2894 if (FD_ISSET (fdp->fd, &write_set))
2895 fdp->revents |= _DBUS_POLLOUT;
2896
2897 if (FD_ISSET (fdp->fd, &err_set))
2898 fdp->revents |= _DBUS_POLLERR;
2899 }
2900 }
2901
2902 return ready;
2903#endif
2904}
2905
2913void
2915 long *tv_usec)
2916{
2917#ifdef HAVE_MONOTONIC_CLOCK
2918 struct timespec ts;
2919 clock_gettime (CLOCK_MONOTONIC, &ts);
2920
2921 if (tv_sec)
2922 *tv_sec = ts.tv_sec;
2923 if (tv_usec)
2924 *tv_usec = ts.tv_nsec / 1000;
2925#else
2926 struct timeval t;
2927
2928 gettimeofday (&t, NULL);
2929
2930 if (tv_sec)
2931 *tv_sec = t.tv_sec;
2932 if (tv_usec)
2933 *tv_usec = t.tv_usec;
2934#endif
2935}
2936
2944void
2946 long *tv_usec)
2947{
2948 struct timeval t;
2949
2950 gettimeofday (&t, NULL);
2951
2952 if (tv_sec)
2953 *tv_sec = t.tv_sec;
2954 if (tv_usec)
2955 *tv_usec = t.tv_usec;
2956}
2957
2968 DBusError *error)
2969{
2970 const char *filename_c;
2971
2972 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2973
2974 filename_c = _dbus_string_get_const_data (filename);
2975
2976 if (mkdir (filename_c, 0700) < 0)
2977 {
2978 if (errno == EEXIST)
2979 return TRUE;
2980
2982 "Failed to create directory %s: %s\n",
2983 filename_c, _dbus_strerror (errno));
2984 return FALSE;
2985 }
2986 else
2987 return TRUE;
2988}
2989
3000 DBusError *error)
3001{
3002 const char *filename_c;
3003
3004 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3005
3006 filename_c = _dbus_string_get_const_data (filename);
3007
3008 if (mkdir (filename_c, 0700) < 0)
3009 {
3011 "Failed to create directory %s: %s\n",
3012 filename_c, _dbus_strerror (errno));
3013 return FALSE;
3014 }
3015 else
3016 return TRUE;
3017}
3018
3031 const DBusString *next_component)
3032{
3033 dbus_bool_t dir_ends_in_slash;
3034 dbus_bool_t file_starts_with_slash;
3035
3036 if (_dbus_string_get_length (dir) == 0 ||
3037 _dbus_string_get_length (next_component) == 0)
3038 return TRUE;
3039
3040 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3041 _dbus_string_get_length (dir) - 1);
3042
3043 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3044
3045 if (dir_ends_in_slash && file_starts_with_slash)
3046 {
3047 _dbus_string_shorten (dir, 1);
3048 }
3049 else if (!(dir_ends_in_slash || file_starts_with_slash))
3050 {
3051 if (!_dbus_string_append_byte (dir, '/'))
3052 return FALSE;
3053 }
3054
3055 return _dbus_string_copy (next_component, 0, dir,
3056 _dbus_string_get_length (dir));
3057}
3058
3060#define NANOSECONDS_PER_SECOND 1000000000
3062#define MICROSECONDS_PER_SECOND 1000000
3064#define MILLISECONDS_PER_SECOND 1000
3066#define NANOSECONDS_PER_MILLISECOND 1000000
3068#define MICROSECONDS_PER_MILLISECOND 1000
3069
3074void
3076{
3077#ifdef HAVE_NANOSLEEP
3078 struct timespec req;
3079 struct timespec rem;
3080
3081 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3082 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3083 rem.tv_sec = 0;
3084 rem.tv_nsec = 0;
3085
3086 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3087 req = rem;
3088#elif defined (HAVE_USLEEP)
3089 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3090#else /* ! HAVE_USLEEP */
3091 sleep (MAX (milliseconds / 1000, 1));
3092#endif
3093}
3094
3106 int n_bytes,
3107 DBusError *error)
3108{
3109 int old_len;
3110 int fd;
3111 int result;
3112
3113 old_len = _dbus_string_get_length (str);
3114 fd = -1;
3115
3116 /* note, urandom on linux will fall back to pseudorandom */
3117 fd = open ("/dev/urandom", O_RDONLY);
3118
3119 if (fd < 0)
3120 {
3121 dbus_set_error (error, _dbus_error_from_errno (errno),
3122 "Could not open /dev/urandom: %s",
3123 _dbus_strerror (errno));
3124 return FALSE;
3125 }
3126
3127 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3128
3129 result = _dbus_read (fd, str, n_bytes);
3130
3131 if (result != n_bytes)
3132 {
3133 if (result < 0)
3134 dbus_set_error (error, _dbus_error_from_errno (errno),
3135 "Could not read /dev/urandom: %s",
3136 _dbus_strerror (errno));
3137 else
3139 "Short read from /dev/urandom");
3140
3141 _dbus_close (fd, NULL);
3142 _dbus_string_set_length (str, old_len);
3143 return FALSE;
3144 }
3145
3146 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3147 n_bytes);
3148
3149 _dbus_close (fd, NULL);
3150
3151 return TRUE;
3152}
3153
3159void
3160_dbus_exit (int code)
3161{
3162 _exit (code);
3163}
3164
3173const char*
3174_dbus_strerror (int error_number)
3175{
3176 const char *msg;
3177
3178 msg = strerror (error_number);
3179 if (msg == NULL)
3180 msg = "unknown";
3181
3182 return msg;
3183}
3184
3188void
3190{
3191 signal (SIGPIPE, SIG_IGN);
3192}
3193
3201void
3203{
3204 int val;
3205
3206 val = fcntl (fd, F_GETFD, 0);
3207
3208 if (val < 0)
3209 return;
3210
3211 val |= FD_CLOEXEC;
3212
3213 fcntl (fd, F_SETFD, val);
3214}
3215
3225 DBusError *error)
3226{
3227 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3228
3229 again:
3230 if (close (fd) < 0)
3231 {
3232 if (errno == EINTR)
3233 goto again;
3234
3235 dbus_set_error (error, _dbus_error_from_errno (errno),
3236 "Could not close fd %d", fd);
3237 return FALSE;
3238 }
3239
3240 return TRUE;
3241}
3242
3251int
3253 DBusError *error)
3254{
3255 int new_fd;
3256
3257#ifdef F_DUPFD_CLOEXEC
3258 dbus_bool_t cloexec_done;
3259
3260 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3261 cloexec_done = new_fd >= 0;
3262
3263 if (new_fd < 0 && errno == EINVAL)
3264#endif
3265 {
3266 new_fd = fcntl(fd, F_DUPFD, 3);
3267 }
3268
3269 if (new_fd < 0) {
3270
3271 dbus_set_error (error, _dbus_error_from_errno (errno),
3272 "Could not duplicate fd %d", fd);
3273 return -1;
3274 }
3275
3276#ifdef F_DUPFD_CLOEXEC
3277 if (!cloexec_done)
3278#endif
3279 {
3281 }
3282
3283 return new_fd;
3284}
3285
3295 DBusError *error)
3296{
3297 return _dbus_set_fd_nonblocking (fd.fd, error);
3298}
3299
3300static dbus_bool_t
3301_dbus_set_fd_nonblocking (int fd,
3302 DBusError *error)
3303{
3304 int val;
3305
3306 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3307
3308 val = fcntl (fd, F_GETFL, 0);
3309 if (val < 0)
3310 {
3311 dbus_set_error (error, _dbus_error_from_errno (errno),
3312 "Failed to get flags from file descriptor %d: %s",
3313 fd, _dbus_strerror (errno));
3314 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3315 _dbus_strerror (errno));
3316 return FALSE;
3317 }
3318
3319 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3320 {
3321 dbus_set_error (error, _dbus_error_from_errno (errno),
3322 "Failed to set nonblocking flag of file descriptor %d: %s",
3323 fd, _dbus_strerror (errno));
3324 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3325 fd, _dbus_strerror (errno));
3326
3327 return FALSE;
3328 }
3329
3330 return TRUE;
3331}
3332
3338void
3340{
3341#if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3342 void *bt[500];
3343 int bt_size;
3344 int i;
3345 char **syms;
3346
3347 bt_size = backtrace (bt, 500);
3348
3349 syms = backtrace_symbols (bt, bt_size);
3350
3351 i = 0;
3352 while (i < bt_size)
3353 {
3354 /* don't use dbus_warn since it can _dbus_abort() */
3355 fprintf (stderr, " %s\n", syms[i]);
3356 ++i;
3357 }
3358 fflush (stderr);
3359
3360 free (syms);
3361#elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3362 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3363#else
3364 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3365#endif
3366}
3367
3382 DBusSocket *fd2,
3383 dbus_bool_t blocking,
3384 DBusError *error)
3385{
3386#ifdef HAVE_SOCKETPAIR
3387 int fds[2];
3388 int retval;
3389
3390#ifdef SOCK_CLOEXEC
3391 dbus_bool_t cloexec_done;
3392
3393 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3394 cloexec_done = retval >= 0;
3395
3396 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3397#endif
3398 {
3399 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3400 }
3401
3402 if (retval < 0)
3403 {
3404 dbus_set_error (error, _dbus_error_from_errno (errno),
3405 "Could not create full-duplex pipe");
3406 return FALSE;
3407 }
3408
3409 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3410
3411#ifdef SOCK_CLOEXEC
3412 if (!cloexec_done)
3413#endif
3414 {
3417 }
3418
3419 if (!blocking &&
3420 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3421 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3422 {
3423 dbus_set_error (error, _dbus_error_from_errno (errno),
3424 "Could not set full-duplex pipe nonblocking");
3425
3426 _dbus_close (fds[0], NULL);
3427 _dbus_close (fds[1], NULL);
3428
3429 return FALSE;
3430 }
3431
3432 fd1->fd = fds[0];
3433 fd2->fd = fds[1];
3434
3435 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3436 fd1->fd, fd2->fd);
3437
3438 return TRUE;
3439#else
3440 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3442 "_dbus_socketpair() not implemented on this OS");
3443 return FALSE;
3444#endif
3445}
3446
3455int
3457 va_list args)
3458{
3459 char static_buf[1024];
3460 int bufsize = sizeof (static_buf);
3461 int len;
3462 va_list args_copy;
3463
3464 DBUS_VA_COPY (args_copy, args);
3465 len = vsnprintf (static_buf, bufsize, format, args_copy);
3466 va_end (args_copy);
3467
3468 /* If vsnprintf() returned non-negative, then either the string fits in
3469 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3470 * returns the number of characters that were needed, or this OS returns the
3471 * truncated length.
3472 *
3473 * We ignore the possibility that snprintf might just ignore the length and
3474 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3475 * If your libc is really that bad, come back when you have a better one. */
3476 if (len == bufsize)
3477 {
3478 /* This could be the truncated length (Tru64 and IRIX have this bug),
3479 * or the real length could be coincidentally the same. Which is it?
3480 * If vsnprintf returns the truncated length, we'll go to the slow
3481 * path. */
3482 DBUS_VA_COPY (args_copy, args);
3483
3484 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3485 len = -1;
3486
3487 va_end (args_copy);
3488 }
3489
3490 /* If vsnprintf() returned negative, we have to do more work.
3491 * HP-UX returns negative. */
3492 while (len < 0)
3493 {
3494 char *buf;
3495
3496 bufsize *= 2;
3497
3498 buf = dbus_malloc (bufsize);
3499
3500 if (buf == NULL)
3501 return -1;
3502
3503 DBUS_VA_COPY (args_copy, args);
3504 len = vsnprintf (buf, bufsize, format, args_copy);
3505 va_end (args_copy);
3506
3507 dbus_free (buf);
3508
3509 /* If the reported length is exactly the buffer size, round up to the
3510 * next size, in case vsnprintf has been returning the truncated
3511 * length */
3512 if (len == bufsize)
3513 len = -1;
3514 }
3515
3516 return len;
3517}
3518
3525const char*
3527{
3528 /* Protected by _DBUS_LOCK_sysdeps */
3529 static const char* tmpdir = NULL;
3530
3531 if (!_DBUS_LOCK (sysdeps))
3532 return NULL;
3533
3534 if (tmpdir == NULL)
3535 {
3536 /* TMPDIR is what glibc uses, then
3537 * glibc falls back to the P_tmpdir macro which
3538 * just expands to "/tmp"
3539 */
3540 if (tmpdir == NULL)
3541 tmpdir = getenv("TMPDIR");
3542
3543 /* These two env variables are probably
3544 * broken, but maybe some OS uses them?
3545 */
3546 if (tmpdir == NULL)
3547 tmpdir = getenv("TMP");
3548 if (tmpdir == NULL)
3549 tmpdir = getenv("TEMP");
3550
3551 /* And this is the sane fallback. */
3552 if (tmpdir == NULL)
3553 tmpdir = "/tmp";
3554 }
3555
3556 _DBUS_UNLOCK (sysdeps);
3557
3558 _dbus_assert(tmpdir != NULL);
3559
3560 return tmpdir;
3561}
3562
3563#if 1
3583static dbus_bool_t
3584_read_subprocess_line_argv (const char *progpath,
3585 dbus_bool_t path_fallback,
3586 const char * const *argv,
3587 DBusString *result,
3588 DBusError *error)
3589{
3590 int result_pipe[2] = { -1, -1 };
3591 int errors_pipe[2] = { -1, -1 };
3592 pid_t pid;
3593 int ret;
3594 int status;
3595 int orig_len;
3596
3597 dbus_bool_t retval;
3598 sigset_t new_set, old_set;
3599
3600 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3601 retval = FALSE;
3602
3603 /* We need to block any existing handlers for SIGCHLD temporarily; they
3604 * will cause waitpid() below to fail.
3605 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3606 */
3607 sigemptyset (&new_set);
3608 sigaddset (&new_set, SIGCHLD);
3609 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3610
3611 orig_len = _dbus_string_get_length (result);
3612
3613#define READ_END 0
3614#define WRITE_END 1
3615 if (pipe (result_pipe) < 0)
3616 {
3617 dbus_set_error (error, _dbus_error_from_errno (errno),
3618 "Failed to create a pipe to call %s: %s",
3619 progpath, _dbus_strerror (errno));
3620 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3621 progpath, _dbus_strerror (errno));
3622 goto out;
3623 }
3624 if (pipe (errors_pipe) < 0)
3625 {
3626 dbus_set_error (error, _dbus_error_from_errno (errno),
3627 "Failed to create a pipe to call %s: %s",
3628 progpath, _dbus_strerror (errno));
3629 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3630 progpath, _dbus_strerror (errno));
3631 goto out;
3632 }
3633
3634 pid = fork ();
3635 if (pid < 0)
3636 {
3637 dbus_set_error (error, _dbus_error_from_errno (errno),
3638 "Failed to fork() to call %s: %s",
3639 progpath, _dbus_strerror (errno));
3640 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3641 progpath, _dbus_strerror (errno));
3642 goto out;
3643 }
3644
3645 if (pid == 0)
3646 {
3647 /* child process */
3648 const char *error_str;
3649
3650 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3651 {
3652 int saved_errno = errno;
3653
3654 /* Try to write details into the pipe, but don't bother
3655 * trying too hard (no retry loop). */
3656
3657 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
3658 write (errors_pipe[WRITE_END], ": ", 2) < 0)
3659 {
3660 /* ignore, not much we can do */
3661 }
3662
3663 error_str = _dbus_strerror (saved_errno);
3664
3665 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
3666 {
3667 /* ignore, not much we can do */
3668 }
3669
3670 _exit (1);
3671 }
3672
3673 /* set-up stdXXX */
3674 close (result_pipe[READ_END]);
3675 close (errors_pipe[READ_END]);
3676
3677 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3678 _exit (1);
3679 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3680 _exit (1);
3681
3682 _dbus_close_all ();
3683
3684 sigprocmask (SIG_SETMASK, &old_set, NULL);
3685
3686 /* If it looks fully-qualified, try execv first */
3687 if (progpath[0] == '/')
3688 {
3689 execv (progpath, (char * const *) argv);
3690 /* Ok, that failed. Now if path_fallback is given, let's
3691 * try unqualified. This is mostly a hack to work
3692 * around systems which ship dbus-launch in /usr/bin
3693 * but everything else in /bin (because dbus-launch
3694 * depends on X11).
3695 */
3696 if (path_fallback)
3697 /* We must have a slash, because we checked above */
3698 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
3699 }
3700 else
3701 execvp (progpath, (char * const *) argv);
3702
3703 /* still nothing, we failed */
3704 _exit (1);
3705 }
3706
3707 /* parent process */
3708 close (result_pipe[WRITE_END]);
3709 close (errors_pipe[WRITE_END]);
3710 result_pipe[WRITE_END] = -1;
3711 errors_pipe[WRITE_END] = -1;
3712
3713 ret = 0;
3714 do
3715 {
3716 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3717 }
3718 while (ret > 0);
3719
3720 /* reap the child process to avoid it lingering as zombie */
3721 do
3722 {
3723 ret = waitpid (pid, &status, 0);
3724 }
3725 while (ret == -1 && errno == EINTR);
3726
3727 /* We succeeded if the process exited with status 0 and
3728 anything was read */
3729 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3730 {
3731 /* The process ended with error */
3732 DBusString error_message;
3733 if (!_dbus_string_init (&error_message))
3734 {
3735 _DBUS_SET_OOM (error);
3736 goto out;
3737 }
3738
3739 ret = 0;
3740 do
3741 {
3742 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3743 }
3744 while (ret > 0);
3745
3746 _dbus_string_set_length (result, orig_len);
3747 if (_dbus_string_get_length (&error_message) > 0)
3749 "%s terminated abnormally with the following error: %s",
3750 progpath, _dbus_string_get_data (&error_message));
3751 else
3753 "%s terminated abnormally without any error message",
3754 progpath);
3755 goto out;
3756 }
3757
3758 retval = TRUE;
3759
3760 out:
3761 sigprocmask (SIG_SETMASK, &old_set, NULL);
3762
3763 if (retval)
3764 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3765 else
3766 _DBUS_ASSERT_ERROR_IS_SET (error);
3767
3768 if (result_pipe[0] != -1)
3769 close (result_pipe[0]);
3770 if (result_pipe[1] != -1)
3771 close (result_pipe[1]);
3772 if (errors_pipe[0] != -1)
3773 close (errors_pipe[0]);
3774 if (errors_pipe[1] != -1)
3775 close (errors_pipe[1]);
3776
3777 return retval;
3778}
3779#endif
3780
3795 DBusString *address,
3796 DBusError *error)
3797{
3798#if 1
3799 static const char arg_dbus_launch[] = "dbus-launch";
3800 static const char arg_autolaunch[] = "--autolaunch";
3801 static const char arg_binary_syntax[] = "--binary-syntax";
3802 static const char arg_close_stderr[] = "--close-stderr";
3803
3804 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3805 * but that's done elsewhere, and if it worked, this function wouldn't
3806 * be called.) */
3807 const char *display;
3808 const char *progpath;
3809 const char *argv[6];
3810 int i;
3811 DBusString uuid;
3812 dbus_bool_t retval;
3813
3814 if (_dbus_check_setuid ())
3815 {
3817 "Unable to autolaunch when setuid");
3818 return FALSE;
3819 }
3820
3821 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3822 retval = FALSE;
3823
3824 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3825 * dbus-launch-x11 is just going to fail. Rather than trying to
3826 * run it, we might as well bail out early with a nice error.
3827 *
3828 * This is not strictly true in a world where the user bus exists,
3829 * because dbus-launch --autolaunch knows how to connect to that -
3830 * but if we were going to connect to the user bus, we'd have done
3831 * so before trying autolaunch: in any case. */
3832 display = _dbus_getenv ("DISPLAY");
3833
3834 if (display == NULL || display[0] == '\0')
3835 {
3837 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3838 return FALSE;
3839 }
3840
3841 if (!_dbus_string_init (&uuid))
3842 {
3843 _DBUS_SET_OOM (error);
3844 return FALSE;
3845 }
3846
3847 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3848 {
3849 goto out;
3850 }
3851
3852#ifdef DBUS_ENABLE_EMBEDDED_TESTS
3853 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3854
3855 if (progpath == NULL)
3856#endif
3857 progpath = DBUS_BINDIR "/dbus-launch";
3858 /*
3859 * argv[0] is always dbus-launch, that's the name what we'll
3860 * get from /proc, or ps(1), regardless what the progpath is,
3861 * see fd.o#69716
3862 */
3863 i = 0;
3864 argv[i] = arg_dbus_launch;
3865 ++i;
3866 argv[i] = arg_autolaunch;
3867 ++i;
3868 argv[i] = _dbus_string_get_data (&uuid);
3869 ++i;
3870 argv[i] = arg_binary_syntax;
3871 ++i;
3872 argv[i] = arg_close_stderr;
3873 ++i;
3874 argv[i] = NULL;
3875 ++i;
3876
3877 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3878
3879 retval = _read_subprocess_line_argv (progpath,
3880 TRUE,
3881 argv, address, error);
3882
3883 out:
3884 _dbus_string_free (&uuid);
3885 return retval;
3886#else
3888 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3889 "set your DBUS_SESSION_BUS_ADDRESS instead");
3890 return FALSE;
3891#endif
3892}
3893
3914 dbus_bool_t create_if_not_found,
3915 DBusError *error)
3916{
3917 DBusError our_error = DBUS_ERROR_INIT;
3918 DBusError etc_error = DBUS_ERROR_INIT;
3919 DBusString filename;
3920 dbus_bool_t b;
3921
3922 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3923
3924 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
3925 if (b)
3926 return TRUE;
3927
3928 /* Fallback to the system machine ID */
3929 _dbus_string_init_const (&filename, "/etc/machine-id");
3930 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
3931
3932 if (b)
3933 {
3934 if (create_if_not_found)
3935 {
3936 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3937 * complain if that isn't possible for whatever reason */
3938 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3939 _dbus_write_uuid_file (&filename, machine_id, NULL);
3940 }
3941
3942 dbus_error_free (&our_error);
3943 return TRUE;
3944 }
3945
3946 if (!create_if_not_found)
3947 {
3948 dbus_set_error (error, etc_error.name,
3949 "D-Bus library appears to be incorrectly set up: "
3950 "see the manual page for dbus-uuidgen to correct "
3951 "this issue. (%s; %s)",
3952 our_error.message, etc_error.message);
3953 dbus_error_free (&our_error);
3954 dbus_error_free (&etc_error);
3955 return FALSE;
3956 }
3957
3958 dbus_error_free (&our_error);
3959 dbus_error_free (&etc_error);
3960
3961 /* if none found, try to make a new one */
3962 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3963
3964 if (!_dbus_generate_uuid (machine_id, error))
3965 return FALSE;
3966
3967 return _dbus_write_uuid_file (&filename, machine_id, error);
3968}
3969
3979 const char *launchd_env_var,
3980 DBusError *error)
3981{
3982#ifdef DBUS_ENABLE_LAUNCHD
3983 char *argv[4];
3984 int i;
3985
3986 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3987
3988 if (_dbus_check_setuid ())
3989 {
3991 "Unable to find launchd socket when setuid");
3992 return FALSE;
3993 }
3994
3995 i = 0;
3996 argv[i] = "launchctl";
3997 ++i;
3998 argv[i] = "getenv";
3999 ++i;
4000 argv[i] = (char*)launchd_env_var;
4001 ++i;
4002 argv[i] = NULL;
4003 ++i;
4004
4005 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4006
4007 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4008 {
4009 return FALSE;
4010 }
4011
4012 /* no error, but no result either */
4013 if (_dbus_string_get_length(socket_path) == 0)
4014 {
4015 return FALSE;
4016 }
4017
4018 /* strip the carriage-return */
4019 _dbus_string_shorten(socket_path, 1);
4020 return TRUE;
4021#else /* DBUS_ENABLE_LAUNCHD */
4023 "can't lookup socket from launchd; launchd support not compiled in");
4024 return FALSE;
4025#endif
4026}
4027
4028#ifdef DBUS_ENABLE_LAUNCHD
4029static dbus_bool_t
4030_dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4031{
4032 dbus_bool_t valid_socket;
4033 DBusString socket_path;
4034
4035 if (_dbus_check_setuid ())
4036 {
4038 "Unable to find launchd socket when setuid");
4039 return FALSE;
4040 }
4041
4042 if (!_dbus_string_init (&socket_path))
4043 {
4044 _DBUS_SET_OOM (error);
4045 return FALSE;
4046 }
4047
4048 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4049
4050 if (dbus_error_is_set(error))
4051 {
4052 _dbus_string_free(&socket_path);
4053 return FALSE;
4054 }
4055
4056 if (!valid_socket)
4057 {
4058 dbus_set_error(error, "no socket path",
4059 "launchd did not provide a socket path, "
4060 "verify that org.freedesktop.dbus-session.plist is loaded!");
4061 _dbus_string_free(&socket_path);
4062 return FALSE;
4063 }
4064 if (!_dbus_string_append (address, "unix:path="))
4065 {
4066 _DBUS_SET_OOM (error);
4067 _dbus_string_free(&socket_path);
4068 return FALSE;
4069 }
4070 if (!_dbus_string_copy (&socket_path, 0, address,
4071 _dbus_string_get_length (address)))
4072 {
4073 _DBUS_SET_OOM (error);
4074 _dbus_string_free(&socket_path);
4075 return FALSE;
4076 }
4077
4078 _dbus_string_free(&socket_path);
4079 return TRUE;
4080}
4081#endif
4082
4084_dbus_lookup_user_bus (dbus_bool_t *supported,
4085 DBusString *address,
4086 DBusError *error)
4087{
4088 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4089 dbus_bool_t ret = FALSE;
4090 struct stat stbuf;
4091 DBusString user_bus_path;
4092
4093 if (runtime_dir == NULL)
4094 {
4095 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4096 *supported = FALSE;
4097 return TRUE; /* Cannot use it, but not an error */
4098 }
4099
4100 if (!_dbus_string_init (&user_bus_path))
4101 {
4102 _DBUS_SET_OOM (error);
4103 return FALSE;
4104 }
4105
4106 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4107 {
4108 _DBUS_SET_OOM (error);
4109 goto out;
4110 }
4111
4112 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4113 {
4114 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4115 _dbus_strerror (errno));
4116 *supported = FALSE;
4117 ret = TRUE; /* Cannot use it, but not an error */
4118 goto out;
4119 }
4120
4121 if (stbuf.st_uid != getuid ())
4122 {
4123 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4124 (long) stbuf.st_uid, (long) getuid ());
4125 *supported = FALSE;
4126 ret = TRUE; /* Cannot use it, but not an error */
4127 goto out;
4128 }
4129
4130 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4131 {
4132 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4133 (long) stbuf.st_mode);
4134 *supported = FALSE;
4135 ret = TRUE; /* Cannot use it, but not an error */
4136 goto out;
4137 }
4138
4139 if (!_dbus_string_append (address, "unix:path=") ||
4140 !_dbus_address_append_escaped (address, &user_bus_path))
4141 {
4142 _DBUS_SET_OOM (error);
4143 goto out;
4144 }
4145
4146 *supported = TRUE;
4147 ret = TRUE;
4148
4149out:
4150 _dbus_string_free (&user_bus_path);
4151 return ret;
4152}
4153
4175 DBusString *address,
4176 DBusError *error)
4177{
4178#ifdef DBUS_ENABLE_LAUNCHD
4179 *supported = TRUE;
4180 return _dbus_lookup_session_address_launchd (address, error);
4181#else
4182 *supported = FALSE;
4183
4184 if (!_dbus_lookup_user_bus (supported, address, error))
4185 return FALSE;
4186 else if (*supported)
4187 return TRUE;
4188
4189 /* On non-Mac Unix platforms, if the session address isn't already
4190 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4191 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4192 * autolaunch: global default; see init_session_address in
4193 * dbus/dbus-bus.c. */
4194 return TRUE;
4195#endif
4196}
4197
4205void
4210
4226 DBusCredentials *credentials)
4227{
4228 DBusString homedir;
4229 DBusString dotdir;
4230 dbus_uid_t uid;
4231
4232 _dbus_assert (credentials != NULL);
4234
4235 if (!_dbus_string_init (&homedir))
4236 return FALSE;
4237
4238 uid = _dbus_credentials_get_unix_uid (credentials);
4240
4241 if (!_dbus_homedir_from_uid (uid, &homedir))
4242 goto failed;
4243
4244#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4245 {
4246 const char *override;
4247
4248 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4249 if (override != NULL && *override != '\0')
4250 {
4251 _dbus_string_set_length (&homedir, 0);
4252 if (!_dbus_string_append (&homedir, override))
4253 goto failed;
4254
4255 _dbus_verbose ("Using fake homedir for testing: %s\n",
4256 _dbus_string_get_const_data (&homedir));
4257 }
4258 else
4259 {
4260 /* Not strictly thread-safe, but if we fail at thread-safety here,
4261 * the worst that will happen is some extra warnings. */
4262 static dbus_bool_t already_warned = FALSE;
4263 if (!already_warned)
4264 {
4265 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4266 _dbus_string_get_const_data (&homedir));
4267 already_warned = TRUE;
4268 }
4269 }
4270 }
4271#endif
4272
4273 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4274 if (!_dbus_concat_dir_and_file (&homedir,
4275 &dotdir))
4276 goto failed;
4277
4278 if (!_dbus_string_copy (&homedir, 0,
4279 directory, _dbus_string_get_length (directory))) {
4280 goto failed;
4281 }
4282
4283 _dbus_string_free (&homedir);
4284 return TRUE;
4285
4286 failed:
4287 _dbus_string_free (&homedir);
4288 return FALSE;
4289}
4290
4291//PENDING(kdab) docs
4293_dbus_daemon_publish_session_bus_address (const char* addr,
4294 const char *scope)
4295{
4296 return TRUE;
4297}
4298
4299//PENDING(kdab) docs
4300void
4301_dbus_daemon_unpublish_session_bus_address (void)
4302{
4303
4304}
4305
4314{
4315 return e == EAGAIN || e == EWOULDBLOCK;
4316}
4317
4327 DBusError *error)
4328{
4329 const char *filename_c;
4330
4331 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4332
4333 filename_c = _dbus_string_get_const_data (filename);
4334
4335 if (rmdir (filename_c) != 0)
4336 {
4338 "Failed to remove directory %s: %s\n",
4339 filename_c, _dbus_strerror (errno));
4340 return FALSE;
4341 }
4342
4343 return TRUE;
4344}
4345
4355{
4356#ifdef SCM_RIGHTS
4357 union {
4358 struct sockaddr sa;
4359 struct sockaddr_storage storage;
4360 struct sockaddr_un un;
4361 } sa_buf;
4362
4363 socklen_t sa_len = sizeof(sa_buf);
4364
4365 _DBUS_ZERO(sa_buf);
4366
4367 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4368 return FALSE;
4369
4370 return sa_buf.sa.sa_family == AF_UNIX;
4371
4372#else
4373 return FALSE;
4374
4375#endif
4376}
4377
4382void
4384{
4385 int maxfds, i;
4386
4387#ifdef __linux__
4388 DIR *d;
4389
4390 /* On Linux we can optimize this a bit if /proc is available. If it
4391 isn't available, fall back to the brute force way. */
4392
4393 d = opendir ("/proc/self/fd");
4394 if (d)
4395 {
4396 for (;;)
4397 {
4398 struct dirent *de;
4399 int fd;
4400 long l;
4401 char *e = NULL;
4402
4403 de = readdir (d);
4404 if (!de)
4405 break;
4406
4407 if (de->d_name[0] == '.')
4408 continue;
4409
4410 errno = 0;
4411 l = strtol (de->d_name, &e, 10);
4412 if (errno != 0 || e == NULL || *e != '\0')
4413 continue;
4414
4415 fd = (int) l;
4416 if (fd < 3)
4417 continue;
4418
4419 if (fd == dirfd (d))
4420 continue;
4421
4422 close (fd);
4423 }
4424
4425 closedir (d);
4426 return;
4427 }
4428#endif
4429
4430 maxfds = sysconf (_SC_OPEN_MAX);
4431
4432 /* Pick something reasonable if for some reason sysconf says
4433 * unlimited.
4434 */
4435 if (maxfds < 0)
4436 maxfds = 1024;
4437
4438 /* close all inherited fds */
4439 for (i = 3; i < maxfds; i++)
4440 close (i);
4441}
4442
4454{
4455 /* TODO: get __libc_enable_secure exported from glibc.
4456 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4457 */
4458#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4459 {
4460 /* See glibc/include/unistd.h */
4461 extern int __libc_enable_secure;
4462 return __libc_enable_secure;
4463 }
4464#elif defined(HAVE_ISSETUGID)
4465 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4466 return issetugid ();
4467#else
4468 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4469 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4470
4471 /* We call into this function from _dbus_threads_init_platform_specific()
4472 * to make sure these are initialized before we start threading. */
4473 static dbus_bool_t check_setuid_initialised;
4474 static dbus_bool_t is_setuid;
4475
4476 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4477 {
4478#ifdef HAVE_GETRESUID
4479 if (getresuid (&ruid, &euid, &suid) != 0 ||
4480 getresgid (&rgid, &egid, &sgid) != 0)
4481#endif /* HAVE_GETRESUID */
4482 {
4483 suid = ruid = getuid ();
4484 sgid = rgid = getgid ();
4485 euid = geteuid ();
4486 egid = getegid ();
4487 }
4488
4489 check_setuid_initialised = TRUE;
4490 is_setuid = (ruid != euid || ruid != suid ||
4491 rgid != egid || rgid != sgid);
4492
4493 }
4494 return is_setuid;
4495#endif
4496}
4497
4507 DBusString *address,
4508 DBusError *error)
4509{
4510 union {
4511 struct sockaddr sa;
4512 struct sockaddr_storage storage;
4513 struct sockaddr_un un;
4514 struct sockaddr_in ipv4;
4515 struct sockaddr_in6 ipv6;
4516 } socket;
4517 char hostip[INET6_ADDRSTRLEN];
4518 socklen_t size = sizeof (socket);
4519 DBusString path_str;
4520
4521 if (getsockname (fd.fd, &socket.sa, &size))
4522 goto err;
4523
4524 switch (socket.sa.sa_family)
4525 {
4526 case AF_UNIX:
4527 if (socket.un.sun_path[0]=='\0')
4528 {
4529 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4530 if (_dbus_string_append (address, "unix:abstract=") &&
4531 _dbus_address_append_escaped (address, &path_str))
4532 return TRUE;
4533 }
4534 else
4535 {
4536 _dbus_string_init_const (&path_str, socket.un.sun_path);
4537 if (_dbus_string_append (address, "unix:path=") &&
4538 _dbus_address_append_escaped (address, &path_str))
4539 return TRUE;
4540 }
4541 break;
4542 case AF_INET:
4543 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4544 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4545 hostip, ntohs (socket.ipv4.sin_port)))
4546 return TRUE;
4547 break;
4548#ifdef AF_INET6
4549 case AF_INET6:
4550 _dbus_string_init_const (&path_str, hostip);
4551 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4552 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4553 ntohs (socket.ipv6.sin6_port)) &&
4554 _dbus_address_append_escaped (address, &path_str))
4555 return TRUE;
4556 break;
4557#endif
4558 default:
4559 dbus_set_error (error,
4560 _dbus_error_from_errno (EINVAL),
4561 "Failed to read address from socket: Unknown socket type.");
4562 return FALSE;
4563 }
4564 err:
4565 dbus_set_error (error,
4566 _dbus_error_from_errno (errno),
4567 "Failed to open socket: %s",
4568 _dbus_strerror (errno));
4569 return FALSE;
4570}
4571
4572int
4573_dbus_save_socket_errno (void)
4574{
4575 return errno;
4576}
4577
4578void
4579_dbus_restore_socket_errno (int saved_errno)
4580{
4581 errno = saved_errno;
4582}
4583
4584static const char *syslog_tag = "dbus";
4585#ifdef HAVE_SYSLOG_H
4586static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4587#endif
4588
4603void
4604_dbus_init_system_log (const char *tag,
4605 DBusLogFlags flags)
4606{
4607 /* We never want to turn off logging completely */
4608 _dbus_assert (
4609 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4610
4611 syslog_tag = tag;
4612
4613#ifdef HAVE_SYSLOG_H
4614 log_flags = flags;
4615
4616 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4617 openlog (tag, LOG_PID, LOG_DAEMON);
4618#endif
4619}
4620
4628void
4629_dbus_logv (DBusSystemLogSeverity severity,
4630 const char *msg,
4631 va_list args)
4632{
4633 va_list tmp;
4634#ifdef HAVE_SYSLOG_H
4635 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4636 {
4637 int flags;
4638 switch (severity)
4639 {
4640 case DBUS_SYSTEM_LOG_INFO:
4641 flags = LOG_DAEMON | LOG_INFO;
4642 break;
4643 case DBUS_SYSTEM_LOG_WARNING:
4644 flags = LOG_DAEMON | LOG_WARNING;
4645 break;
4646 case DBUS_SYSTEM_LOG_SECURITY:
4647 flags = LOG_AUTH | LOG_NOTICE;
4648 break;
4649 case DBUS_SYSTEM_LOG_ERROR:
4650 flags = LOG_DAEMON|LOG_CRIT;
4651 break;
4652 default:
4653 _dbus_assert_not_reached ("invalid log severity");
4654 }
4655
4656 DBUS_VA_COPY (tmp, args);
4657 vsyslog (flags, msg, tmp);
4658 va_end (tmp);
4659 }
4660
4661 /* If we don't have syslog.h, we always behave as though stderr was in
4662 * the flags */
4663 if (log_flags & DBUS_LOG_FLAGS_STDERR)
4664#endif
4665 {
4666 DBUS_VA_COPY (tmp, args);
4667 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
4668 vfprintf (stderr, msg, tmp);
4669 fputc ('\n', stderr);
4670 va_end (tmp);
4671 }
4672}
4673
4674/* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_address_append_escaped(DBusString *escaped, const DBusString *unescaped)
Appends an escaped version of one string to another string, using the D-Bus address escaping mechanis...
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
dbus_uid_t _dbus_credentials_get_unix_uid(DBusCredentials *credentials)
Gets the UNIX user ID in the credentials, or DBUS_UID_UNSET if the credentials object doesn't contain...
dbus_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.
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.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
#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.
Definition dbus-spawn.c:888
#define WRITE_END
Helps remember which end of the pipe is which.
Definition dbus-spawn.c:890
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
dbus_bool_t _dbus_homedir_from_uid(dbus_uid_t uid, DBusString *homedir)
Gets the home directory for the given user.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:49
#define TRUE
Expands to "1".
Definition dbus-macros.h:39
#define FALSE
Expands to "0".
Definition dbus-macros.h:42
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_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition dbus-memory.h:58
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_parse_int(const DBusString *str, int start, long *value_return, int *end_return)
Parses an integer contained in a DBusString.
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
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.
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.
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_parse_uid(const DBusString *uid_str, dbus_uid_t *uid)
Gets a UID from a UID string.
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.
unsigned long dbus_uid_t
A user ID.
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.
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
void _dbus_exit(int code)
Exit the process, returning the given value.
#define _DBUS_POLLERR
Error condition.
dbus_bool_t _dbus_socket_can_pass_unix_fd(DBusSocket fd)
Checks whether file descriptors may be passed via the socket.
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Like _dbus_write(), but only supports sockets and is thus available on Windows.
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.
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
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
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
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
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.
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 credentials of the current process to the passed-in credentials object.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with.
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul.
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
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.
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR,...
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
int dbus_int32_t
A 32-bit signed integer on all platforms.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:35
An atomic integer safe to increment or decrement from multiple threads.
volatile dbus_int32_t value
Value of the atomic integer.
Object representing an exception.
Definition dbus-errors.h: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
short events
Events to poll for.
short revents
Events that occurred.
DBusPollable fd
File descriptor.
Socket interface.
Information about a UNIX user.
int n_group_ids
Size of group IDs array.
dbus_uid_t uid
UID.
char * homedir
Home directory.
dbus_gid_t * group_ids
Groups IDs, including above primary group.
char * username
Username.
dbus_gid_t primary_gid
GID.
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...