D-Bus 1.12.20
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;
445 size_t fds_to_use;
446
447 /* Every unsigned int fits in a size_t without truncation, so
448 * casting (size_t) *n_fds is OK */
449 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int));
450
451 if ((m.msg_flags & MSG_CTRUNC) && CMSG_NXTHDR(&m, cm) == NULL &&
452 (char *) payload + payload_len_bytes >
453 (char *) m.msg_control + m.msg_controllen)
454 {
455 /* This is the last cmsg in a truncated message and using
456 * cmsg_len would apparently overrun the allocated buffer.
457 * Some operating systems (illumos and Solaris are known) do
458 * not adjust cmsg_len in the last cmsg when truncation occurs.
459 * Adjust the payload length here. The calculation for
460 * payload_len_fds below will discard any trailing bytes that
461 * belong to an incomplete file descriptor - the kernel will
462 * have already closed that (at least for illumos and Solaris)
463 */
464 payload_len_bytes = m.msg_controllen -
465 ((char *) payload - (char *) m.msg_control);
466 }
467
468 payload_len_fds = payload_len_bytes / sizeof (int);
469
470 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
471 {
472 /* The fds in the payload will fit in our buffer */
473 fds_to_use = payload_len_fds;
474 }
475 else
476 {
477 /* Too many fds in the payload. This shouldn't happen
478 * any more because we're setting m.msg_controllen to
479 * the exact number we can accept, but be safe and
480 * truncate. */
481 fds_to_use = (size_t) *n_fds;
482
483 /* Close the excess fds to avoid DoS: if they stayed open,
484 * someone could send us an extra fd per message
485 * and we'd eventually run out. */
486 for (i = fds_to_use; i < payload_len_fds; i++)
487 {
488 close (payload[i]);
489 }
490 }
491
492 memcpy (fds, payload, fds_to_use * sizeof (int));
493 found = TRUE;
494 /* This narrowing cast from size_t to unsigned int cannot
495 * overflow because we have chosen fds_to_use
496 * to be <= *n_fds */
497 *n_fds = (unsigned int) fds_to_use;
498
499 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
500 worked, hence we need to go through this list and set
501 CLOEXEC everywhere in any case */
502 for (i = 0; i < fds_to_use; i++)
504
505 break;
506 }
507
508 if (!found)
509 *n_fds = 0;
510
511 if (m.msg_flags & MSG_CTRUNC)
512 {
513 unsigned int i;
514
515 /* Hmm, apparently the control data was truncated. The bad
516 thing is that we might have completely lost a couple of fds
517 without chance to recover them. Hence let's treat this as a
518 serious error. */
519
520 /* We still need to close whatever fds we *did* receive,
521 * otherwise they'll never get closed. (CVE-2020-12049) */
522 for (i = 0; i < *n_fds; i++)
523 close (fds[i]);
524
525 *n_fds = 0;
526 errno = ENOSPC;
527 _dbus_string_set_length (buffer, start);
528 return -1;
529 }
530
531 /* put length back (doesn't actually realloc) */
532 _dbus_string_set_length (buffer, start + bytes_read);
533
534#if 0
535 if (bytes_read > 0)
536 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
537#endif
538
539 return bytes_read;
540 }
541#endif
542}
543
544int
545_dbus_write_socket_with_unix_fds(DBusSocket fd,
546 const DBusString *buffer,
547 int start,
548 int len,
549 const int *fds,
550 int n_fds) {
551
552#ifndef HAVE_UNIX_FD_PASSING
553
554 if (n_fds > 0) {
555 errno = ENOTSUP;
556 return -1;
557 }
558
559 return _dbus_write_socket(fd, buffer, start, len);
560#else
561 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
562#endif
563}
564
565int
566_dbus_write_socket_with_unix_fds_two(DBusSocket fd,
567 const DBusString *buffer1,
568 int start1,
569 int len1,
570 const DBusString *buffer2,
571 int start2,
572 int len2,
573 const int *fds,
574 int n_fds) {
575
576#ifndef HAVE_UNIX_FD_PASSING
577
578 if (n_fds > 0) {
579 errno = ENOTSUP;
580 return -1;
581 }
582
583 return _dbus_write_socket_two(fd,
584 buffer1, start1, len1,
585 buffer2, start2, len2);
586#else
587
588 struct msghdr m;
589 struct cmsghdr *cm;
590 struct iovec iov[2];
591 int bytes_written;
592
593 _dbus_assert (len1 >= 0);
594 _dbus_assert (len2 >= 0);
595 _dbus_assert (n_fds >= 0);
596
597 _DBUS_ZERO(iov);
598 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
599 iov[0].iov_len = len1;
600
601 if (buffer2)
602 {
603 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
604 iov[1].iov_len = len2;
605 }
606
607 _DBUS_ZERO(m);
608 m.msg_iov = iov;
609 m.msg_iovlen = buffer2 ? 2 : 1;
610
611 if (n_fds > 0)
612 {
613 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
614 m.msg_control = alloca(m.msg_controllen);
615 memset(m.msg_control, 0, m.msg_controllen);
616
617 cm = CMSG_FIRSTHDR(&m);
618 cm->cmsg_level = SOL_SOCKET;
619 cm->cmsg_type = SCM_RIGHTS;
620 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
621 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
622 }
623
624 again:
625
626 bytes_written = sendmsg (fd.fd, &m, 0
627#if HAVE_DECL_MSG_NOSIGNAL
628 |MSG_NOSIGNAL
629#endif
630 );
631
632 if (bytes_written < 0 && errno == EINTR)
633 goto again;
634
635#if 0
636 if (bytes_written > 0)
637 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
638#endif
639
640 return bytes_written;
641#endif
642}
643
657int
659 const DBusString *buffer1,
660 int start1,
661 int len1,
662 const DBusString *buffer2,
663 int start2,
664 int len2)
665{
666#if HAVE_DECL_MSG_NOSIGNAL
667 struct iovec vectors[2];
668 const char *data1;
669 const char *data2;
670 int bytes_written;
671 struct msghdr m;
672
673 _dbus_assert (buffer1 != NULL);
674 _dbus_assert (start1 >= 0);
675 _dbus_assert (start2 >= 0);
676 _dbus_assert (len1 >= 0);
677 _dbus_assert (len2 >= 0);
678
679 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
680
681 if (buffer2 != NULL)
682 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
683 else
684 {
685 data2 = NULL;
686 start2 = 0;
687 len2 = 0;
688 }
689
690 vectors[0].iov_base = (char*) data1;
691 vectors[0].iov_len = len1;
692 vectors[1].iov_base = (char*) data2;
693 vectors[1].iov_len = len2;
694
695 _DBUS_ZERO(m);
696 m.msg_iov = vectors;
697 m.msg_iovlen = data2 ? 2 : 1;
698
699 again:
700
701 bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
702
703 if (bytes_written < 0 && errno == EINTR)
704 goto again;
705
706 return bytes_written;
707
708#else
709 return _dbus_write_two (fd.fd, buffer1, start1, len1,
710 buffer2, start2, len2);
711#endif
712}
713
730int
732 DBusString *buffer,
733 int count)
734{
735 int bytes_read;
736 int start;
737 char *data;
738
739 _dbus_assert (count >= 0);
740
741 start = _dbus_string_get_length (buffer);
742
743 if (!_dbus_string_lengthen (buffer, count))
744 {
745 errno = ENOMEM;
746 return -1;
747 }
748
749 data = _dbus_string_get_data_len (buffer, start, count);
750
751 again:
752
753 bytes_read = read (fd, data, count);
754
755 if (bytes_read < 0)
756 {
757 if (errno == EINTR)
758 goto again;
759 else
760 {
761 /* put length back (note that this doesn't actually realloc anything) */
762 _dbus_string_set_length (buffer, start);
763 return -1;
764 }
765 }
766 else
767 {
768 /* put length back (doesn't actually realloc) */
769 _dbus_string_set_length (buffer, start + bytes_read);
770
771#if 0
772 if (bytes_read > 0)
773 _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
774#endif
775
776 return bytes_read;
777 }
778}
779
790int
792 const DBusString *buffer,
793 int start,
794 int len)
795{
796 const char *data;
797 int bytes_written;
798
799 data = _dbus_string_get_const_data_len (buffer, start, len);
800
801 again:
802
803 bytes_written = write (fd, data, len);
804
805 if (bytes_written < 0 && errno == EINTR)
806 goto again;
807
808#if 0
809 if (bytes_written > 0)
810 _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
811#endif
812
813 return bytes_written;
814}
815
836int
838 const DBusString *buffer1,
839 int start1,
840 int len1,
841 const DBusString *buffer2,
842 int start2,
843 int len2)
844{
845 _dbus_assert (buffer1 != NULL);
846 _dbus_assert (start1 >= 0);
847 _dbus_assert (start2 >= 0);
848 _dbus_assert (len1 >= 0);
849 _dbus_assert (len2 >= 0);
850
851#ifdef HAVE_WRITEV
852 {
853 struct iovec vectors[2];
854 const char *data1;
855 const char *data2;
856 int bytes_written;
857
858 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
859
860 if (buffer2 != NULL)
861 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
862 else
863 {
864 data2 = NULL;
865 start2 = 0;
866 len2 = 0;
867 }
868
869 vectors[0].iov_base = (char*) data1;
870 vectors[0].iov_len = len1;
871 vectors[1].iov_base = (char*) data2;
872 vectors[1].iov_len = len2;
873
874 again:
875
876 bytes_written = writev (fd,
877 vectors,
878 data2 ? 2 : 1);
879
880 if (bytes_written < 0 && errno == EINTR)
881 goto again;
882
883 return bytes_written;
884 }
885#else /* HAVE_WRITEV */
886 {
887 int ret1, ret2;
888
889 ret1 = _dbus_write (fd, buffer1, start1, len1);
890 if (ret1 == len1 && buffer2 != NULL)
891 {
892 ret2 = _dbus_write (fd, buffer2, start2, len2);
893 if (ret2 < 0)
894 ret2 = 0; /* we can't report an error as the first write was OK */
895
896 return ret1 + ret2;
897 }
898 else
899 return ret1;
900 }
901#endif /* !HAVE_WRITEV */
902}
903
904#define _DBUS_MAX_SUN_PATH_LENGTH 99
905
935int
937 dbus_bool_t abstract,
938 DBusError *error)
939{
940 int fd;
941 size_t path_len;
942 struct sockaddr_un addr;
943 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
944
945 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
946
947 _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
948 path, abstract);
949
950
951 if (!_dbus_open_unix_socket (&fd, error))
952 {
953 _DBUS_ASSERT_ERROR_IS_SET(error);
954 return -1;
955 }
956 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
957
958 _DBUS_ZERO (addr);
959 addr.sun_family = AF_UNIX;
960 path_len = strlen (path);
961
962 if (abstract)
963 {
964#ifdef __linux__
965 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
966 path_len++; /* Account for the extra nul byte added to the start of sun_path */
967
968 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
969 {
971 "Abstract socket name too long\n");
972 _dbus_close (fd, NULL);
973 return -1;
974 }
975
976 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
977 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
978#else /* !__linux__ */
980 "Operating system does not support abstract socket namespace\n");
981 _dbus_close (fd, NULL);
982 return -1;
983#endif /* !__linux__ */
984 }
985 else
986 {
987 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
988 {
990 "Socket name too long\n");
991 _dbus_close (fd, NULL);
992 return -1;
993 }
994
995 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
996 }
997
998 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
999 {
1000 dbus_set_error (error,
1001 _dbus_error_from_errno (errno),
1002 "Failed to connect to socket %s: %s",
1003 path, _dbus_strerror (errno));
1004
1005 _dbus_close (fd, NULL);
1006 return -1;
1007 }
1008
1009 if (!_dbus_set_fd_nonblocking (fd, error))
1010 {
1011 _DBUS_ASSERT_ERROR_IS_SET (error);
1012
1013 _dbus_close (fd, NULL);
1014 return -1;
1015 }
1016
1017 return fd;
1018}
1019
1032int
1033_dbus_connect_exec (const char *path,
1034 char *const argv[],
1035 DBusError *error)
1036{
1037 int fds[2];
1038 pid_t pid;
1039 int retval;
1040 dbus_bool_t cloexec_done = 0;
1041
1042 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1043
1044 _dbus_verbose ("connecting to process %s\n", path);
1045
1046#ifdef SOCK_CLOEXEC
1047 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1048 cloexec_done = (retval >= 0);
1049
1050 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1051#endif
1052 {
1053 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1054 }
1055
1056 if (retval < 0)
1057 {
1058 dbus_set_error (error,
1059 _dbus_error_from_errno (errno),
1060 "Failed to create socket pair: %s",
1061 _dbus_strerror (errno));
1062 return -1;
1063 }
1064
1065 if (!cloexec_done)
1066 {
1069 }
1070
1071 pid = fork ();
1072 if (pid < 0)
1073 {
1074 dbus_set_error (error,
1075 _dbus_error_from_errno (errno),
1076 "Failed to fork() to call %s: %s",
1077 path, _dbus_strerror (errno));
1078 close (fds[0]);
1079 close (fds[1]);
1080 return -1;
1081 }
1082
1083 if (pid == 0)
1084 {
1085 /* child */
1086 close (fds[0]);
1087
1088 dup2 (fds[1], STDIN_FILENO);
1089 dup2 (fds[1], STDOUT_FILENO);
1090
1091 if (fds[1] != STDIN_FILENO &&
1092 fds[1] != STDOUT_FILENO)
1093 close (fds[1]);
1094
1095 /* Inherit STDERR and the controlling terminal from the
1096 parent */
1097
1098 _dbus_close_all ();
1099
1100 execvp (path, (char * const *) argv);
1101
1102 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1103
1104 _exit(1);
1105 }
1106
1107 /* parent */
1108 close (fds[1]);
1109
1110 if (!_dbus_set_fd_nonblocking (fds[0], error))
1111 {
1112 _DBUS_ASSERT_ERROR_IS_SET (error);
1113
1114 close (fds[0]);
1115 return -1;
1116 }
1117
1118 return fds[0];
1119}
1120
1138int
1140 dbus_bool_t abstract,
1141 DBusError *error)
1142{
1143 int listen_fd;
1144 struct sockaddr_un addr;
1145 size_t path_len;
1146 _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1147
1148 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1149
1150 _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1151 path, abstract);
1152
1153 if (!_dbus_open_unix_socket (&listen_fd, error))
1154 {
1155 _DBUS_ASSERT_ERROR_IS_SET(error);
1156 return -1;
1157 }
1158 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1159
1160 _DBUS_ZERO (addr);
1161 addr.sun_family = AF_UNIX;
1162 path_len = strlen (path);
1163
1164 if (abstract)
1165 {
1166#ifdef __linux__
1167 /* remember that abstract names aren't nul-terminated so we rely
1168 * on sun_path being filled in with zeroes above.
1169 */
1170 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1171 path_len++; /* Account for the extra nul byte added to the start of sun_path */
1172
1173 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1174 {
1176 "Abstract socket name too long\n");
1177 _dbus_close (listen_fd, NULL);
1178 return -1;
1179 }
1180
1181 strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1182 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1183#else /* !__linux__ */
1185 "Operating system does not support abstract socket namespace\n");
1186 _dbus_close (listen_fd, NULL);
1187 return -1;
1188#endif /* !__linux__ */
1189 }
1190 else
1191 {
1192 /* Discussed security implications of this with Nalin,
1193 * and we couldn't think of where it would kick our ass, but
1194 * it still seems a bit sucky. It also has non-security suckage;
1195 * really we'd prefer to exit if the socket is already in use.
1196 * But there doesn't seem to be a good way to do this.
1197 *
1198 * Just to be extra careful, I threw in the stat() - clearly
1199 * the stat() can't *fix* any security issue, but it at least
1200 * avoids inadvertent/accidental data loss.
1201 */
1202 {
1203 struct stat sb;
1204
1205 if (stat (path, &sb) == 0 &&
1206 S_ISSOCK (sb.st_mode))
1207 unlink (path);
1208 }
1209
1210 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1211 {
1213 "Socket name too long\n");
1214 _dbus_close (listen_fd, NULL);
1215 return -1;
1216 }
1217
1218 strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1219 }
1220
1221 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1222 {
1223 dbus_set_error (error, _dbus_error_from_errno (errno),
1224 "Failed to bind socket \"%s\": %s",
1225 path, _dbus_strerror (errno));
1226 _dbus_close (listen_fd, NULL);
1227 return -1;
1228 }
1229
1230 if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1231 {
1232 dbus_set_error (error, _dbus_error_from_errno (errno),
1233 "Failed to listen on socket \"%s\": %s",
1234 path, _dbus_strerror (errno));
1235 _dbus_close (listen_fd, NULL);
1236 return -1;
1237 }
1238
1239 if (!_dbus_set_fd_nonblocking (listen_fd, error))
1240 {
1241 _DBUS_ASSERT_ERROR_IS_SET (error);
1242 _dbus_close (listen_fd, NULL);
1243 return -1;
1244 }
1245
1246 /* Try opening up the permissions, but if we can't, just go ahead
1247 * and continue, maybe it will be good enough.
1248 */
1249 if (!abstract && chmod (path, 0777) < 0)
1250 _dbus_warn ("Could not set mode 0777 on socket %s", path);
1251
1252 return listen_fd;
1253}
1254
1265int
1267 DBusError *error)
1268{
1269#ifdef HAVE_SYSTEMD
1270 int r, n;
1271 int fd;
1272 DBusSocket *new_fds;
1273
1274 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1275
1276 n = sd_listen_fds (TRUE);
1277 if (n < 0)
1278 {
1280 "Failed to acquire systemd socket: %s",
1281 _dbus_strerror (-n));
1282 return -1;
1283 }
1284
1285 if (n <= 0)
1286 {
1288 "No socket received.");
1289 return -1;
1290 }
1291
1292 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1293 {
1294 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1295 if (r < 0)
1296 {
1298 "Failed to verify systemd socket type: %s",
1299 _dbus_strerror (-r));
1300 return -1;
1301 }
1302
1303 if (!r)
1304 {
1306 "Passed socket has wrong type.");
1307 return -1;
1308 }
1309 }
1310
1311 /* OK, the file descriptors are all good, so let's take posession of
1312 them then. */
1313
1314 new_fds = dbus_new (DBusSocket, n);
1315 if (!new_fds)
1316 {
1318 "Failed to allocate file handle array.");
1319 goto fail;
1320 }
1321
1322 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1323 {
1324 if (!_dbus_set_fd_nonblocking (fd, error))
1325 {
1326 _DBUS_ASSERT_ERROR_IS_SET (error);
1327 goto fail;
1328 }
1329
1330 new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1331 }
1332
1333 *fds = new_fds;
1334 return n;
1335
1336 fail:
1337
1338 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1339 {
1340 _dbus_close (fd, NULL);
1341 }
1342
1343 dbus_free (new_fds);
1344 return -1;
1345#else
1347 "dbus was compiled without systemd support");
1348 return -1;
1349#endif
1350}
1351
1352/* Convert an error code from getaddrinfo() or getnameinfo() into
1353 * a D-Bus error name. */
1354static const char *
1355_dbus_error_from_gai (int gai_res,
1356 int saved_errno)
1357{
1358 switch (gai_res)
1359 {
1360#ifdef EAI_FAMILY
1361 case EAI_FAMILY:
1362 /* ai_family not supported (at all) */
1364#endif
1365
1366#ifdef EAI_SOCKTYPE
1367 case EAI_SOCKTYPE:
1368 /* ai_socktype not supported (at all) */
1370#endif
1371
1372#ifdef EAI_MEMORY
1373 case EAI_MEMORY:
1374 /* Out of memory */
1375 return DBUS_ERROR_NO_MEMORY;
1376#endif
1377
1378#ifdef EAI_SYSTEM
1379 case EAI_SYSTEM:
1380 /* Unspecified system error, details in errno */
1381 return _dbus_error_from_errno (saved_errno);
1382#endif
1383
1384 case 0:
1385 /* It succeeded, but we didn't get any addresses? */
1386 return DBUS_ERROR_FAILED;
1387
1388 /* EAI_AGAIN: Transient failure */
1389 /* EAI_BADFLAGS: invalid ai_flags (programming error) */
1390 /* EAI_FAIL: Non-recoverable failure */
1391 /* EAI_NODATA: host exists but has no addresses */
1392 /* EAI_NONAME: host does not exist */
1393 /* EAI_OVERFLOW: argument buffer overflow */
1394 /* EAI_SERVICE: service not available for specified socket
1395 * type (we should never see this because we use numeric
1396 * ports) */
1397 default:
1398 return DBUS_ERROR_FAILED;
1399 }
1400}
1401
1417 const char *port,
1418 const char *family,
1419 DBusError *error)
1420{
1421 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1422}
1423
1425_dbus_connect_tcp_socket_with_nonce (const char *host,
1426 const char *port,
1427 const char *family,
1428 const char *noncefile,
1429 DBusError *error)
1430{
1431 int saved_errno = 0;
1432 DBusSocket fd = DBUS_SOCKET_INIT;
1433 int res;
1434 struct addrinfo hints;
1435 struct addrinfo *ai, *tmp;
1436
1437 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1438
1439 _DBUS_ZERO (hints);
1440
1441 if (!family)
1442 hints.ai_family = AF_UNSPEC;
1443 else if (!strcmp(family, "ipv4"))
1444 hints.ai_family = AF_INET;
1445 else if (!strcmp(family, "ipv6"))
1446 hints.ai_family = AF_INET6;
1447 else
1448 {
1449 dbus_set_error (error,
1451 "Unknown address family %s", family);
1452 return _dbus_socket_get_invalid ();
1453 }
1454 hints.ai_protocol = IPPROTO_TCP;
1455 hints.ai_socktype = SOCK_STREAM;
1456 hints.ai_flags = AI_ADDRCONFIG;
1457
1458 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1459 {
1460 dbus_set_error (error,
1461 _dbus_error_from_gai (res, errno),
1462 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1463 host, port, gai_strerror(res), res);
1464 return _dbus_socket_get_invalid ();
1465 }
1466
1467 tmp = ai;
1468 while (tmp)
1469 {
1470 if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1471 {
1472 freeaddrinfo(ai);
1473 _DBUS_ASSERT_ERROR_IS_SET(error);
1474 return _dbus_socket_get_invalid ();
1475 }
1476 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1477
1478 if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1479 {
1480 saved_errno = errno;
1481 _dbus_close (fd.fd, NULL);
1482 fd.fd = -1;
1483 tmp = tmp->ai_next;
1484 continue;
1485 }
1486
1487 break;
1488 }
1489 freeaddrinfo(ai);
1490
1491 if (fd.fd == -1)
1492 {
1493 dbus_set_error (error,
1494 _dbus_error_from_errno (saved_errno),
1495 "Failed to connect to socket \"%s:%s\" %s",
1496 host, port, _dbus_strerror(saved_errno));
1497 return _dbus_socket_get_invalid ();
1498 }
1499
1500 if (noncefile != NULL)
1501 {
1502 DBusString noncefileStr;
1503 dbus_bool_t ret;
1504 _dbus_string_init_const (&noncefileStr, noncefile);
1505 ret = _dbus_send_nonce (fd, &noncefileStr, error);
1506 _dbus_string_free (&noncefileStr);
1507
1508 if (!ret)
1509 {
1510 _dbus_close (fd.fd, NULL);
1511 return _dbus_socket_get_invalid ();
1512 }
1513 }
1514
1515 if (!_dbus_set_fd_nonblocking (fd.fd, error))
1516 {
1517 _dbus_close (fd.fd, NULL);
1518 return _dbus_socket_get_invalid ();
1519 }
1520
1521 return fd;
1522}
1523
1540int
1541_dbus_listen_tcp_socket (const char *host,
1542 const char *port,
1543 const char *family,
1544 DBusString *retport,
1545 DBusSocket **fds_p,
1546 DBusError *error)
1547{
1548 int saved_errno;
1549 int nlisten_fd = 0, res, i;
1550 DBusSocket *listen_fd = NULL;
1551 struct addrinfo hints;
1552 struct addrinfo *ai, *tmp;
1553 unsigned int reuseaddr;
1554
1555 *fds_p = NULL;
1556 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1557
1558 _DBUS_ZERO (hints);
1559
1560 if (!family)
1561 hints.ai_family = AF_UNSPEC;
1562 else if (!strcmp(family, "ipv4"))
1563 hints.ai_family = AF_INET;
1564 else if (!strcmp(family, "ipv6"))
1565 hints.ai_family = AF_INET6;
1566 else
1567 {
1568 dbus_set_error (error,
1570 "Unknown address family %s", family);
1571 return -1;
1572 }
1573
1574 hints.ai_protocol = IPPROTO_TCP;
1575 hints.ai_socktype = SOCK_STREAM;
1576 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1577
1578 redo_lookup_with_port:
1579 ai = NULL;
1580 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1581 {
1582 dbus_set_error (error,
1583 _dbus_error_from_gai (res, errno),
1584 "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1585 host ? host : "*", port, gai_strerror(res), res);
1586 goto failed;
1587 }
1588
1589 tmp = ai;
1590 while (tmp)
1591 {
1592 int fd = -1, tcp_nodelay_on;
1593 DBusSocket *newlisten_fd;
1594
1595 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1596 {
1597 _DBUS_ASSERT_ERROR_IS_SET(error);
1598 goto failed;
1599 }
1600 _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1601
1602 reuseaddr = 1;
1603 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1604 {
1605 _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1606 host ? host : "*", port, _dbus_strerror (errno));
1607 }
1608
1609 /* Nagle's algorithm imposes a huge delay on the initial messages
1610 going over TCP. */
1611 tcp_nodelay_on = 1;
1612 if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1613 {
1614 _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1615 host ? host : "*", port, _dbus_strerror (errno));
1616 }
1617
1618 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1619 {
1620 saved_errno = errno;
1621 _dbus_close(fd, NULL);
1622 if (saved_errno == EADDRINUSE)
1623 {
1624 /* Depending on kernel policy, binding to an IPv6 address
1625 might implicitly bind to a corresponding IPv4
1626 address or vice versa, resulting in EADDRINUSE for the
1627 other one (e.g. bindv6only=0 on Linux).
1628
1629 Also, after we "goto redo_lookup_with_port" after binding
1630 a port on one of the possible addresses, we will
1631 try to bind that same port on every address, including the
1632 same address again for a second time; that one will
1633 also fail with EADDRINUSE.
1634
1635 For both those reasons, ignore EADDRINUSE here */
1636 tmp = tmp->ai_next;
1637 continue;
1638 }
1639 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1640 "Failed to bind socket \"%s:%s\": %s",
1641 host ? host : "*", port, _dbus_strerror (saved_errno));
1642 goto failed;
1643 }
1644
1645 if (listen (fd, 30 /* backlog */) < 0)
1646 {
1647 saved_errno = errno;
1648 _dbus_close (fd, NULL);
1649 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1650 "Failed to listen on socket \"%s:%s\": %s",
1651 host ? host : "*", port, _dbus_strerror (saved_errno));
1652 goto failed;
1653 }
1654
1655 newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1656 if (!newlisten_fd)
1657 {
1658 _dbus_close (fd, NULL);
1660 "Failed to allocate file handle array");
1661 goto failed;
1662 }
1663 listen_fd = newlisten_fd;
1664 listen_fd[nlisten_fd].fd = fd;
1665 nlisten_fd++;
1666
1667 if (!_dbus_string_get_length(retport))
1668 {
1669 /* If the user didn't specify a port, or used 0, then
1670 the kernel chooses a port. After the first address
1671 is bound to, we need to force all remaining addresses
1672 to use the same port */
1673 if (!port || !strcmp(port, "0"))
1674 {
1675 int result;
1676 struct sockaddr_storage addr;
1677 socklen_t addrlen;
1678 char portbuf[50];
1679
1680 addrlen = sizeof(addr);
1681 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1682
1683 if (result == -1)
1684 {
1685 saved_errno = errno;
1686 dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1687 "Failed to retrieve socket name for \"%s:%s\": %s",
1688 host ? host : "*", port, _dbus_strerror (saved_errno));
1689 goto failed;
1690 }
1691
1692 if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1693 portbuf, sizeof(portbuf),
1694 NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1695 {
1696 saved_errno = errno;
1697 dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
1698 "Failed to resolve port \"%s:%s\": %s (%d)",
1699 host ? host : "*", port, gai_strerror(res), res);
1700 goto failed;
1701 }
1702
1703 if (!_dbus_string_append(retport, portbuf))
1704 {
1706 goto failed;
1707 }
1708
1709 /* Release current address list & redo lookup */
1710 port = _dbus_string_get_const_data(retport);
1711 freeaddrinfo(ai);
1712 goto redo_lookup_with_port;
1713 }
1714 else
1715 {
1716 if (!_dbus_string_append(retport, port))
1717 {
1719 goto failed;
1720 }
1721 }
1722 }
1723
1724 tmp = tmp->ai_next;
1725 }
1726 freeaddrinfo(ai);
1727 ai = NULL;
1728
1729 if (!nlisten_fd)
1730 {
1731 errno = EADDRINUSE;
1732 dbus_set_error (error, _dbus_error_from_errno (errno),
1733 "Failed to bind socket \"%s:%s\": %s",
1734 host ? host : "*", port, _dbus_strerror (errno));
1735 goto failed;
1736 }
1737
1738 for (i = 0 ; i < nlisten_fd ; i++)
1739 {
1740 if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1741 {
1742 goto failed;
1743 }
1744 }
1745
1746 *fds_p = listen_fd;
1747
1748 return nlisten_fd;
1749
1750 failed:
1751 if (ai)
1752 freeaddrinfo(ai);
1753 for (i = 0 ; i < nlisten_fd ; i++)
1754 _dbus_close(listen_fd[i].fd, NULL);
1755 dbus_free(listen_fd);
1756 return -1;
1757}
1758
1759static dbus_bool_t
1760write_credentials_byte (int server_fd,
1761 DBusError *error)
1762{
1763 int bytes_written;
1764 char buf[1] = { '\0' };
1765#if defined(HAVE_CMSGCRED)
1766 union {
1767 struct cmsghdr hdr;
1768 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1769 } cmsg;
1770 struct iovec iov;
1771 struct msghdr msg;
1772 iov.iov_base = buf;
1773 iov.iov_len = 1;
1774
1775 _DBUS_ZERO(msg);
1776 msg.msg_iov = &iov;
1777 msg.msg_iovlen = 1;
1778
1779 msg.msg_control = (caddr_t) &cmsg;
1780 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1781 _DBUS_ZERO(cmsg);
1782 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1783 cmsg.hdr.cmsg_level = SOL_SOCKET;
1784 cmsg.hdr.cmsg_type = SCM_CREDS;
1785#endif
1786
1787 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1788
1789 again:
1790
1791#if defined(HAVE_CMSGCRED)
1792 bytes_written = sendmsg (server_fd, &msg, 0
1793#if HAVE_DECL_MSG_NOSIGNAL
1794 |MSG_NOSIGNAL
1795#endif
1796 );
1797
1798 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1799 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1800 * only allows that on AF_UNIX. Try just doing a send() instead. */
1801 if (bytes_written < 0 && errno == EINVAL)
1802#endif
1803 {
1804 bytes_written = send (server_fd, buf, 1, 0
1805#if HAVE_DECL_MSG_NOSIGNAL
1806 |MSG_NOSIGNAL
1807#endif
1808 );
1809 }
1810
1811 if (bytes_written < 0 && errno == EINTR)
1812 goto again;
1813
1814 if (bytes_written < 0)
1815 {
1816 dbus_set_error (error, _dbus_error_from_errno (errno),
1817 "Failed to write credentials byte: %s",
1818 _dbus_strerror (errno));
1819 return FALSE;
1820 }
1821 else if (bytes_written == 0)
1822 {
1824 "wrote zero bytes writing credentials byte");
1825 return FALSE;
1826 }
1827 else
1828 {
1829 _dbus_assert (bytes_written == 1);
1830 _dbus_verbose ("wrote credentials byte\n");
1831 return TRUE;
1832 }
1833}
1834
1835/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1836static dbus_bool_t
1837add_linux_security_label_to_credentials (int client_fd,
1838 DBusCredentials *credentials)
1839{
1840#if defined(__linux__) && defined(SO_PEERSEC)
1841 DBusString buf;
1842 socklen_t len = 1024;
1843 dbus_bool_t oom = FALSE;
1844
1845 if (!_dbus_string_init_preallocated (&buf, len) ||
1846 !_dbus_string_set_length (&buf, len))
1847 return FALSE;
1848
1849 while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1850 _dbus_string_get_data (&buf), &len) < 0)
1851 {
1852 int e = errno;
1853
1854 _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1855 _dbus_strerror (e), (unsigned long) len);
1856
1857 if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1858 {
1859 _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1860 _dbus_strerror (e));
1861 goto out;
1862 }
1863
1864 /* If not enough space, len is updated to be enough.
1865 * Try again with a large enough buffer. */
1866 if (!_dbus_string_set_length (&buf, len))
1867 {
1868 oom = TRUE;
1869 goto out;
1870 }
1871
1872 _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1873 }
1874
1875 if (len <= 0)
1876 {
1877 _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1878 (unsigned long) len);
1879 goto out;
1880 }
1881
1882 if (len > _dbus_string_get_length_uint (&buf))
1883 {
1884 _dbus_verbose ("%lu > %u", (unsigned long) len,
1885 _dbus_string_get_length_uint (&buf));
1886 _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1887 }
1888
1889 if (_dbus_string_get_byte (&buf, len - 1) == 0)
1890 {
1891 /* the kernel included the trailing \0 in its count,
1892 * but DBusString always has an extra \0 after the data anyway */
1893 _dbus_verbose ("subtracting trailing \\0\n");
1894 len--;
1895 }
1896
1897 if (!_dbus_string_set_length (&buf, len))
1898 {
1899 _dbus_assert_not_reached ("shortening string should not lead to OOM");
1900 oom = TRUE;
1901 goto out;
1902 }
1903
1904 if (strlen (_dbus_string_get_const_data (&buf)) != len)
1905 {
1906 /* LSM people on the linux-security-module@ mailing list say this
1907 * should never happen: the label should be a bytestring with
1908 * an optional trailing \0 */
1909 _dbus_verbose ("security label from kernel had an embedded \\0, "
1910 "ignoring it\n");
1911 goto out;
1912 }
1913
1914 _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1915 (unsigned long) len,
1916 _dbus_string_get_const_data (&buf));
1917
1919 _dbus_string_get_const_data (&buf)))
1920 {
1921 oom = TRUE;
1922 goto out;
1923 }
1924
1925out:
1926 _dbus_string_free (&buf);
1927 return !oom;
1928#else
1929 /* no error */
1930 return TRUE;
1931#endif
1932}
1933
1976 DBusCredentials *credentials,
1977 DBusError *error)
1978{
1979 struct msghdr msg;
1980 struct iovec iov;
1981 char buf;
1982 dbus_uid_t uid_read;
1983 dbus_pid_t pid_read;
1984 int bytes_read;
1985
1986#ifdef HAVE_CMSGCRED
1987 union {
1988 struct cmsghdr hdr;
1989 char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1990 } cmsg;
1991#endif
1992
1993 /* The POSIX spec certainly doesn't promise this, but
1994 * we need these assertions to fail as soon as we're wrong about
1995 * it so we can do the porting fixups
1996 */
1997 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1998 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1999 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2000
2001 uid_read = DBUS_UID_UNSET;
2002 pid_read = DBUS_PID_UNSET;
2003
2004 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2005
2006 _dbus_credentials_clear (credentials);
2007
2008 iov.iov_base = &buf;
2009 iov.iov_len = 1;
2010
2011 _DBUS_ZERO(msg);
2012 msg.msg_iov = &iov;
2013 msg.msg_iovlen = 1;
2014
2015#if defined(HAVE_CMSGCRED)
2016 _DBUS_ZERO(cmsg);
2017 msg.msg_control = (caddr_t) &cmsg;
2018 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
2019#endif
2020
2021 again:
2022 bytes_read = recvmsg (client_fd.fd, &msg, 0);
2023
2024 if (bytes_read < 0)
2025 {
2026 if (errno == EINTR)
2027 goto again;
2028
2029 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
2030 * normally only call read_credentials if the socket was ready
2031 * for reading
2032 */
2033
2034 dbus_set_error (error, _dbus_error_from_errno (errno),
2035 "Failed to read credentials byte: %s",
2036 _dbus_strerror (errno));
2037 return FALSE;
2038 }
2039 else if (bytes_read == 0)
2040 {
2041 /* this should not happen unless we are using recvmsg wrong,
2042 * so is essentially here for paranoia
2043 */
2045 "Failed to read credentials byte (zero-length read)");
2046 return FALSE;
2047 }
2048 else if (buf != '\0')
2049 {
2051 "Credentials byte was not nul");
2052 return FALSE;
2053 }
2054
2055 _dbus_verbose ("read credentials byte\n");
2056
2057 {
2058#ifdef SO_PEERCRED
2059 /* Supported by at least Linux and OpenBSD, with minor differences.
2060 *
2061 * This mechanism passes the process ID through and does not require
2062 * the peer's cooperation, so we prefer it over all others. Notably,
2063 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
2064 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
2065 * because this is much less fragile.
2066 */
2067#ifdef __OpenBSD__
2068 struct sockpeercred cr;
2069#else
2070 struct ucred cr;
2071#endif
2072 socklen_t cr_len = sizeof (cr);
2073
2074 if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
2075 {
2076 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
2077 _dbus_strerror (errno));
2078 }
2079 else if (cr_len != sizeof (cr))
2080 {
2081 _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
2082 cr_len, (int) sizeof (cr));
2083 }
2084 else
2085 {
2086 pid_read = cr.pid;
2087 uid_read = cr.uid;
2088 }
2089#elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2090 /* Another variant of the above - used on NetBSD
2091 */
2092 struct unpcbid cr;
2093 socklen_t cr_len = sizeof (cr);
2094
2095 if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2096 {
2097 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2098 _dbus_strerror (errno));
2099 }
2100 else if (cr_len != sizeof (cr))
2101 {
2102 _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2103 cr_len, (int) sizeof (cr));
2104 }
2105 else
2106 {
2107 pid_read = cr.unp_pid;
2108 uid_read = cr.unp_euid;
2109 }
2110#elif defined(HAVE_CMSGCRED)
2111 /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2112 * presence of that struct implies SCM_CREDS. Supported by at least
2113 * FreeBSD and DragonflyBSD.
2114 *
2115 * This mechanism requires the peer to help us (it has to send us a
2116 * SCM_CREDS message) but it does pass the process ID through,
2117 * which makes it better than getpeereid().
2118 */
2119 struct cmsgcred *cred;
2120 struct cmsghdr *cmsgp;
2121
2122 for (cmsgp = CMSG_FIRSTHDR (&msg);
2123 cmsgp != NULL;
2124 cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2125 {
2126 if (cmsgp->cmsg_type == SCM_CREDS &&
2127 cmsgp->cmsg_level == SOL_SOCKET &&
2128 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2129 {
2130 cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2131 pid_read = cred->cmcred_pid;
2132 uid_read = cred->cmcred_euid;
2133 break;
2134 }
2135 }
2136
2137#elif defined(HAVE_GETPEERUCRED)
2138 /* Supported in at least Solaris >= 10. It should probably be higher
2139 * up this list, because it carries the pid and we use this code path
2140 * for audit data. */
2141 ucred_t * ucred = NULL;
2142 if (getpeerucred (client_fd.fd, &ucred) == 0)
2143 {
2144#ifdef HAVE_ADT
2145 adt_session_data_t *adth = NULL;
2146#endif
2147 pid_read = ucred_getpid (ucred);
2148 uid_read = ucred_geteuid (ucred);
2149#ifdef HAVE_ADT
2150 /* generate audit session data based on socket ucred */
2151 if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2152 {
2153 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2154 }
2155 else
2156 {
2157 if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2158 {
2159 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2160 }
2161 else
2162 {
2163 adt_export_data_t *data = NULL;
2164 size_t size = adt_export_session_data (adth, &data);
2165 if (size <= 0)
2166 {
2167 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2168 }
2169 else
2170 {
2171 _dbus_credentials_add_adt_audit_data (credentials, data, size);
2172 free (data);
2173 }
2174 }
2175 (void) adt_end_session (adth);
2176 }
2177#endif /* HAVE_ADT */
2178 }
2179 else
2180 {
2181 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2182 }
2183 if (ucred != NULL)
2184 ucred_free (ucred);
2185
2186 /* ----------------------------------------------------------------
2187 * When adding new mechanisms, please add them above this point
2188 * if they support passing the process ID through, or below if not.
2189 * ---------------------------------------------------------------- */
2190
2191#elif defined(HAVE_GETPEEREID)
2192 /* getpeereid() originates from D.J. Bernstein and is fairly
2193 * widely-supported. According to a web search, it might be present in
2194 * any/all of:
2195 *
2196 * - AIX?
2197 * - Blackberry?
2198 * - Cygwin
2199 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2200 * - Mac OS X
2201 * - Minix 3.1.8+
2202 * - MirBSD?
2203 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2204 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2205 * - QNX?
2206 */
2207 uid_t euid;
2208 gid_t egid;
2209 if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2210 {
2211 uid_read = euid;
2212 }
2213 else
2214 {
2215 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2216 }
2217#else /* no supported mechanism */
2218
2219#warning Socket credentials not supported on this Unix OS
2220#warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2221
2222 /* Please add other operating systems known to support at least one of
2223 * the mechanisms above to this list, keeping alphabetical order.
2224 * Everything not in this list is best-effort.
2225 */
2226#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2227 defined(__linux__) || \
2228 defined(__OpenBSD__) || \
2229 defined(__NetBSD__)
2230# error Credentials passing not working on this OS is a regression!
2231#endif
2232
2233 _dbus_verbose ("Socket credentials not supported on this OS\n");
2234#endif
2235 }
2236
2237 _dbus_verbose ("Credentials:"
2238 " pid "DBUS_PID_FORMAT
2239 " uid "DBUS_UID_FORMAT
2240 "\n",
2241 pid_read,
2242 uid_read);
2243
2244 if (pid_read != DBUS_PID_UNSET)
2245 {
2246 if (!_dbus_credentials_add_pid (credentials, pid_read))
2247 {
2248 _DBUS_SET_OOM (error);
2249 return FALSE;
2250 }
2251 }
2252
2253 if (uid_read != DBUS_UID_UNSET)
2254 {
2255 if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2256 {
2257 _DBUS_SET_OOM (error);
2258 return FALSE;
2259 }
2260 }
2261
2262 if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2263 {
2264 _DBUS_SET_OOM (error);
2265 return FALSE;
2266 }
2267
2268 return TRUE;
2269}
2270
2290 DBusError *error)
2291{
2292 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2293
2294 if (write_credentials_byte (server_fd.fd, error))
2295 return TRUE;
2296 else
2297 return FALSE;
2298}
2299
2311{
2312 DBusSocket client_fd;
2313 struct sockaddr addr;
2314 socklen_t addrlen;
2315#ifdef HAVE_ACCEPT4
2316 dbus_bool_t cloexec_done;
2317#endif
2318
2319 addrlen = sizeof (addr);
2320
2321 retry:
2322
2323#ifdef HAVE_ACCEPT4
2324 /*
2325 * At compile-time, we assume that if accept4() is available in
2326 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2327 * not necessarily true that either is supported by the running kernel.
2328 */
2329 client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2330 cloexec_done = client_fd.fd >= 0;
2331
2332 if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2333#endif
2334 {
2335 client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2336 }
2337
2338 if (client_fd.fd < 0)
2339 {
2340 if (errno == EINTR)
2341 goto retry;
2342 }
2343
2344 _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2345
2346#ifdef HAVE_ACCEPT4
2347 if (!cloexec_done)
2348#endif
2349 {
2350 _dbus_fd_set_close_on_exec(client_fd.fd);
2351 }
2352
2353 return client_fd;
2354}
2355
2366{
2367 const char *directory;
2368 struct stat sb;
2369
2370 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2371
2372 directory = _dbus_string_get_const_data (dir);
2373
2374 if (stat (directory, &sb) < 0)
2375 {
2376 dbus_set_error (error, _dbus_error_from_errno (errno),
2377 "%s", _dbus_strerror (errno));
2378
2379 return FALSE;
2380 }
2381
2382 if (sb.st_uid != geteuid ())
2383 {
2385 "%s directory is owned by user %lu, not %lu",
2386 directory,
2387 (unsigned long) sb.st_uid,
2388 (unsigned long) geteuid ());
2389 return FALSE;
2390 }
2391
2392 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2393 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2394 {
2396 "%s directory is not private to the user", directory);
2397 return FALSE;
2398 }
2399
2400 return TRUE;
2401}
2402
2403static dbus_bool_t
2404fill_user_info_from_passwd (struct passwd *p,
2405 DBusUserInfo *info,
2406 DBusError *error)
2407{
2408 _dbus_assert (p->pw_name != NULL);
2409 _dbus_assert (p->pw_dir != NULL);
2410
2411 info->uid = p->pw_uid;
2412 info->primary_gid = p->pw_gid;
2413 info->username = _dbus_strdup (p->pw_name);
2414 info->homedir = _dbus_strdup (p->pw_dir);
2415
2416 if (info->username == NULL ||
2417 info->homedir == NULL)
2418 {
2420 return FALSE;
2421 }
2422
2423 return TRUE;
2424}
2425
2426static dbus_bool_t
2427fill_user_info (DBusUserInfo *info,
2428 dbus_uid_t uid,
2429 const DBusString *username,
2430 DBusError *error)
2431{
2432 const char *username_c;
2433
2434 /* exactly one of username/uid provided */
2435 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2436 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2437
2438 info->uid = DBUS_UID_UNSET;
2440 info->group_ids = NULL;
2441 info->n_group_ids = 0;
2442 info->username = NULL;
2443 info->homedir = NULL;
2444
2445 if (username != NULL)
2446 username_c = _dbus_string_get_const_data (username);
2447 else
2448 username_c = NULL;
2449
2450 /* For now assuming that the getpwnam() and getpwuid() flavors
2451 * are always symmetrical, if not we have to add more configure
2452 * checks
2453 */
2454
2455#if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2456 {
2457 struct passwd *p;
2458 int result;
2459 size_t buflen;
2460 char *buf;
2461 struct passwd p_str;
2462
2463 /* retrieve maximum needed size for buf */
2464 buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2465
2466 /* sysconf actually returns a long, but everything else expects size_t,
2467 * so just recast here.
2468 * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2469 */
2470 if ((long) buflen <= 0)
2471 buflen = 1024;
2472
2473 result = -1;
2474 while (1)
2475 {
2476 buf = dbus_malloc (buflen);
2477 if (buf == NULL)
2478 {
2480 return FALSE;
2481 }
2482
2483 p = NULL;
2484#ifdef HAVE_POSIX_GETPWNAM_R
2485 if (uid != DBUS_UID_UNSET)
2486 result = getpwuid_r (uid, &p_str, buf, buflen,
2487 &p);
2488 else
2489 result = getpwnam_r (username_c, &p_str, buf, buflen,
2490 &p);
2491#else
2492 if (uid != DBUS_UID_UNSET)
2493 p = getpwuid_r (uid, &p_str, buf, buflen);
2494 else
2495 p = getpwnam_r (username_c, &p_str, buf, buflen);
2496 result = 0;
2497#endif /* !HAVE_POSIX_GETPWNAM_R */
2498 //Try a bigger buffer if ERANGE was returned
2499 if (result == ERANGE && buflen < 512 * 1024)
2500 {
2501 dbus_free (buf);
2502 buflen *= 2;
2503 }
2504 else
2505 {
2506 break;
2507 }
2508 }
2509 if (result == 0 && p == &p_str)
2510 {
2511 if (!fill_user_info_from_passwd (p, info, error))
2512 {
2513 dbus_free (buf);
2514 return FALSE;
2515 }
2516 dbus_free (buf);
2517 }
2518 else
2519 {
2520 dbus_set_error (error, _dbus_error_from_errno (errno),
2521 "User \"%s\" unknown or no memory to allocate password entry\n",
2522 username_c ? username_c : "???");
2523 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2524 dbus_free (buf);
2525 return FALSE;
2526 }
2527 }
2528#else /* ! HAVE_GETPWNAM_R */
2529 {
2530 /* I guess we're screwed on thread safety here */
2531 struct passwd *p;
2532
2533 if (uid != DBUS_UID_UNSET)
2534 p = getpwuid (uid);
2535 else
2536 p = getpwnam (username_c);
2537
2538 if (p != NULL)
2539 {
2540 if (!fill_user_info_from_passwd (p, info, error))
2541 {
2542 return FALSE;
2543 }
2544 }
2545 else
2546 {
2547 dbus_set_error (error, _dbus_error_from_errno (errno),
2548 "User \"%s\" unknown or no memory to allocate password entry\n",
2549 username_c ? username_c : "???");
2550 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2551 return FALSE;
2552 }
2553 }
2554#endif /* ! HAVE_GETPWNAM_R */
2555
2556 /* Fill this in so we can use it to get groups */
2557 username_c = info->username;
2558
2559#ifdef HAVE_GETGROUPLIST
2560 {
2561 gid_t *buf;
2562 int buf_count;
2563 int i;
2564 int initial_buf_count;
2565
2566 initial_buf_count = 17;
2567 buf_count = initial_buf_count;
2568 buf = dbus_new (gid_t, buf_count);
2569 if (buf == NULL)
2570 {
2572 goto failed;
2573 }
2574
2575 if (getgrouplist (username_c,
2576 info->primary_gid,
2577 buf, &buf_count) < 0)
2578 {
2579 gid_t *new;
2580 /* Presumed cause of negative return code: buf has insufficient
2581 entries to hold the entire group list. The Linux behavior in this
2582 case is to pass back the actual number of groups in buf_count, but
2583 on Mac OS X 10.5, buf_count is unhelpfully left alone.
2584 So as a hack, try to help out a bit by guessing a larger
2585 number of groups, within reason.. might still fail, of course,
2586 but we can at least print a more informative message. I looked up
2587 the "right way" to do this by downloading Apple's own source code
2588 for the "id" command, and it turns out that they use an
2589 undocumented library function getgrouplist_2 (!) which is not
2590 declared in any header in /usr/include (!!). That did not seem
2591 like the way to go here.
2592 */
2593 if (buf_count == initial_buf_count)
2594 {
2595 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2596 }
2597 new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2598 if (new == NULL)
2599 {
2601 dbus_free (buf);
2602 goto failed;
2603 }
2604
2605 buf = new;
2606
2607 errno = 0;
2608 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2609 {
2610 if (errno == 0)
2611 {
2612 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2613 username_c, buf_count, buf_count);
2614 }
2615 else
2616 {
2617 dbus_set_error (error,
2618 _dbus_error_from_errno (errno),
2619 "Failed to get groups for username \"%s\" primary GID "
2620 DBUS_GID_FORMAT ": %s\n",
2621 username_c, info->primary_gid,
2622 _dbus_strerror (errno));
2623 dbus_free (buf);
2624 goto failed;
2625 }
2626 }
2627 }
2628
2629 info->group_ids = dbus_new (dbus_gid_t, buf_count);
2630 if (info->group_ids == NULL)
2631 {
2633 dbus_free (buf);
2634 goto failed;
2635 }
2636
2637 for (i = 0; i < buf_count; ++i)
2638 info->group_ids[i] = buf[i];
2639
2640 info->n_group_ids = buf_count;
2641
2642 dbus_free (buf);
2643 }
2644#else /* HAVE_GETGROUPLIST */
2645 {
2646 /* We just get the one group ID */
2647 info->group_ids = dbus_new (dbus_gid_t, 1);
2648 if (info->group_ids == NULL)
2649 {
2651 goto failed;
2652 }
2653
2654 info->n_group_ids = 1;
2655
2656 (info->group_ids)[0] = info->primary_gid;
2657 }
2658#endif /* HAVE_GETGROUPLIST */
2659
2660 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2661
2662 return TRUE;
2663
2664 failed:
2665 _DBUS_ASSERT_ERROR_IS_SET (error);
2666 return FALSE;
2667}
2668
2679 const DBusString *username,
2680 DBusError *error)
2681{
2682 return fill_user_info (info, DBUS_UID_UNSET,
2683 username, error);
2684}
2685
2696 dbus_uid_t uid,
2697 DBusError *error)
2698{
2699 return fill_user_info (info, uid,
2700 NULL, error);
2701}
2702
2712{
2713 /* The POSIX spec certainly doesn't promise this, but
2714 * we need these assertions to fail as soon as we're wrong about
2715 * it so we can do the porting fixups
2716 */
2717 _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2718 _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2719 _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2720
2721 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2722 return FALSE;
2723 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2724 return FALSE;
2725
2726 return TRUE;
2727}
2728
2742{
2743 return _dbus_string_append_uint (str,
2744 _dbus_geteuid ());
2745}
2746
2753{
2754 return getpid ();
2755}
2756
2762{
2763 return getuid ();
2764}
2765
2771{
2772 return geteuid ();
2773}
2774
2781unsigned long
2783{
2784 return getpid ();
2785}
2786
2796 dbus_uid_t *uid)
2797{
2798 int end;
2799 long val;
2800
2801 if (_dbus_string_get_length (uid_str) == 0)
2802 {
2803 _dbus_verbose ("UID string was zero length\n");
2804 return FALSE;
2805 }
2806
2807 val = -1;
2808 end = 0;
2809 if (!_dbus_string_parse_int (uid_str, 0, &val,
2810 &end))
2811 {
2812 _dbus_verbose ("could not parse string as a UID\n");
2813 return FALSE;
2814 }
2815
2816 if (end != _dbus_string_get_length (uid_str))
2817 {
2818 _dbus_verbose ("string contained trailing stuff after UID\n");
2819 return FALSE;
2820 }
2821
2822 *uid = val;
2823
2824 return TRUE;
2825}
2826
2827#if !DBUS_USE_SYNC
2828/* To be thread-safe by default on platforms that don't necessarily have
2829 * atomic operations (notably Debian armel, which is armv4t), we must
2830 * use a mutex that can be initialized statically, like this.
2831 * GLib >= 2.32 uses a similar system.
2832 */
2833static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2834#endif
2835
2842dbus_int32_t
2844{
2845#if DBUS_USE_SYNC
2846 return __sync_add_and_fetch(&atomic->value, 1)-1;
2847#else
2848 dbus_int32_t res;
2849
2850 pthread_mutex_lock (&atomic_mutex);
2851 res = atomic->value;
2852 atomic->value += 1;
2853 pthread_mutex_unlock (&atomic_mutex);
2854
2855 return res;
2856#endif
2857}
2858
2865dbus_int32_t
2867{
2868#if DBUS_USE_SYNC
2869 return __sync_sub_and_fetch(&atomic->value, 1)+1;
2870#else
2871 dbus_int32_t res;
2872
2873 pthread_mutex_lock (&atomic_mutex);
2874 res = atomic->value;
2875 atomic->value -= 1;
2876 pthread_mutex_unlock (&atomic_mutex);
2877
2878 return res;
2879#endif
2880}
2881
2889dbus_int32_t
2891{
2892#if DBUS_USE_SYNC
2893 __sync_synchronize ();
2894 return atomic->value;
2895#else
2896 dbus_int32_t res;
2897
2898 pthread_mutex_lock (&atomic_mutex);
2899 res = atomic->value;
2900 pthread_mutex_unlock (&atomic_mutex);
2901
2902 return res;
2903#endif
2904}
2905
2914int
2916 int n_fds,
2917 int timeout_milliseconds)
2918{
2919#if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2920 /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2921 if (timeout_milliseconds < -1)
2922 {
2923 timeout_milliseconds = -1;
2924 }
2925
2926 return poll (fds,
2927 n_fds,
2928 timeout_milliseconds);
2929#else /* ! HAVE_POLL */
2930 /* Emulate poll() in terms of select() */
2931 fd_set read_set, write_set, err_set;
2932 int max_fd = 0;
2933 int i;
2934 struct timeval tv;
2935 int ready;
2936
2937 FD_ZERO (&read_set);
2938 FD_ZERO (&write_set);
2939 FD_ZERO (&err_set);
2940
2941 for (i = 0; i < n_fds; i++)
2942 {
2943 DBusPollFD *fdp = &fds[i];
2944
2945 if (fdp->events & _DBUS_POLLIN)
2946 FD_SET (fdp->fd, &read_set);
2947
2948 if (fdp->events & _DBUS_POLLOUT)
2949 FD_SET (fdp->fd, &write_set);
2950
2951 FD_SET (fdp->fd, &err_set);
2952
2953 max_fd = MAX (max_fd, fdp->fd);
2954 }
2955
2956 tv.tv_sec = timeout_milliseconds / 1000;
2957 tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2958
2959 ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2960 timeout_milliseconds < 0 ? NULL : &tv);
2961
2962 if (ready > 0)
2963 {
2964 for (i = 0; i < n_fds; i++)
2965 {
2966 DBusPollFD *fdp = &fds[i];
2967
2968 fdp->revents = 0;
2969
2970 if (FD_ISSET (fdp->fd, &read_set))
2971 fdp->revents |= _DBUS_POLLIN;
2972
2973 if (FD_ISSET (fdp->fd, &write_set))
2974 fdp->revents |= _DBUS_POLLOUT;
2975
2976 if (FD_ISSET (fdp->fd, &err_set))
2977 fdp->revents |= _DBUS_POLLERR;
2978 }
2979 }
2980
2981 return ready;
2982#endif
2983}
2984
2992void
2994 long *tv_usec)
2995{
2996#ifdef HAVE_MONOTONIC_CLOCK
2997 struct timespec ts;
2998 clock_gettime (CLOCK_MONOTONIC, &ts);
2999
3000 if (tv_sec)
3001 *tv_sec = ts.tv_sec;
3002 if (tv_usec)
3003 *tv_usec = ts.tv_nsec / 1000;
3004#else
3005 struct timeval t;
3006
3007 gettimeofday (&t, NULL);
3008
3009 if (tv_sec)
3010 *tv_sec = t.tv_sec;
3011 if (tv_usec)
3012 *tv_usec = t.tv_usec;
3013#endif
3014}
3015
3023void
3025 long *tv_usec)
3026{
3027 struct timeval t;
3028
3029 gettimeofday (&t, NULL);
3030
3031 if (tv_sec)
3032 *tv_sec = t.tv_sec;
3033 if (tv_usec)
3034 *tv_usec = t.tv_usec;
3035}
3036
3047 DBusError *error)
3048{
3049 const char *filename_c;
3050
3051 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3052
3053 filename_c = _dbus_string_get_const_data (filename);
3054
3055 if (mkdir (filename_c, 0700) < 0)
3056 {
3057 if (errno == EEXIST)
3058 return TRUE;
3059
3061 "Failed to create directory %s: %s\n",
3062 filename_c, _dbus_strerror (errno));
3063 return FALSE;
3064 }
3065 else
3066 return TRUE;
3067}
3068
3079 DBusError *error)
3080{
3081 const char *filename_c;
3082
3083 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3084
3085 filename_c = _dbus_string_get_const_data (filename);
3086
3087 if (mkdir (filename_c, 0700) < 0)
3088 {
3090 "Failed to create directory %s: %s\n",
3091 filename_c, _dbus_strerror (errno));
3092 return FALSE;
3093 }
3094 else
3095 return TRUE;
3096}
3097
3110 const DBusString *next_component)
3111{
3112 dbus_bool_t dir_ends_in_slash;
3113 dbus_bool_t file_starts_with_slash;
3114
3115 if (_dbus_string_get_length (dir) == 0 ||
3116 _dbus_string_get_length (next_component) == 0)
3117 return TRUE;
3118
3119 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3120 _dbus_string_get_length (dir) - 1);
3121
3122 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3123
3124 if (dir_ends_in_slash && file_starts_with_slash)
3125 {
3126 _dbus_string_shorten (dir, 1);
3127 }
3128 else if (!(dir_ends_in_slash || file_starts_with_slash))
3129 {
3130 if (!_dbus_string_append_byte (dir, '/'))
3131 return FALSE;
3132 }
3133
3134 return _dbus_string_copy (next_component, 0, dir,
3135 _dbus_string_get_length (dir));
3136}
3137
3139#define NANOSECONDS_PER_SECOND 1000000000
3141#define MICROSECONDS_PER_SECOND 1000000
3143#define MILLISECONDS_PER_SECOND 1000
3145#define NANOSECONDS_PER_MILLISECOND 1000000
3147#define MICROSECONDS_PER_MILLISECOND 1000
3148
3153void
3155{
3156#ifdef HAVE_NANOSLEEP
3157 struct timespec req;
3158 struct timespec rem;
3159
3160 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3161 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3162 rem.tv_sec = 0;
3163 rem.tv_nsec = 0;
3164
3165 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3166 req = rem;
3167#elif defined (HAVE_USLEEP)
3168 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3169#else /* ! HAVE_USLEEP */
3170 sleep (MAX (milliseconds / 1000, 1));
3171#endif
3172}
3173
3185 int n_bytes,
3186 DBusError *error)
3187{
3188 int old_len;
3189 int fd;
3190 int result;
3191
3192 old_len = _dbus_string_get_length (str);
3193 fd = -1;
3194
3195 /* note, urandom on linux will fall back to pseudorandom */
3196 fd = open ("/dev/urandom", O_RDONLY);
3197
3198 if (fd < 0)
3199 {
3200 dbus_set_error (error, _dbus_error_from_errno (errno),
3201 "Could not open /dev/urandom: %s",
3202 _dbus_strerror (errno));
3203 return FALSE;
3204 }
3205
3206 _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3207
3208 result = _dbus_read (fd, str, n_bytes);
3209
3210 if (result != n_bytes)
3211 {
3212 if (result < 0)
3213 dbus_set_error (error, _dbus_error_from_errno (errno),
3214 "Could not read /dev/urandom: %s",
3215 _dbus_strerror (errno));
3216 else
3218 "Short read from /dev/urandom");
3219
3220 _dbus_close (fd, NULL);
3221 _dbus_string_set_length (str, old_len);
3222 return FALSE;
3223 }
3224
3225 _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3226 n_bytes);
3227
3228 _dbus_close (fd, NULL);
3229
3230 return TRUE;
3231}
3232
3238void
3239_dbus_exit (int code)
3240{
3241 _exit (code);
3242}
3243
3252const char*
3253_dbus_strerror (int error_number)
3254{
3255 const char *msg;
3256
3257 msg = strerror (error_number);
3258 if (msg == NULL)
3259 msg = "unknown";
3260
3261 return msg;
3262}
3263
3267void
3269{
3270 signal (SIGPIPE, SIG_IGN);
3271}
3272
3280void
3282{
3283 int val;
3284
3285 val = fcntl (fd, F_GETFD, 0);
3286
3287 if (val < 0)
3288 return;
3289
3290 val |= FD_CLOEXEC;
3291
3292 fcntl (fd, F_SETFD, val);
3293}
3294
3304 DBusError *error)
3305{
3306 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3307
3308 again:
3309 if (close (fd) < 0)
3310 {
3311 if (errno == EINTR)
3312 goto again;
3313
3314 dbus_set_error (error, _dbus_error_from_errno (errno),
3315 "Could not close fd %d", fd);
3316 return FALSE;
3317 }
3318
3319 return TRUE;
3320}
3321
3330int
3332 DBusError *error)
3333{
3334 int new_fd;
3335
3336#ifdef F_DUPFD_CLOEXEC
3337 dbus_bool_t cloexec_done;
3338
3339 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3340 cloexec_done = new_fd >= 0;
3341
3342 if (new_fd < 0 && errno == EINVAL)
3343#endif
3344 {
3345 new_fd = fcntl(fd, F_DUPFD, 3);
3346 }
3347
3348 if (new_fd < 0) {
3349
3350 dbus_set_error (error, _dbus_error_from_errno (errno),
3351 "Could not duplicate fd %d", fd);
3352 return -1;
3353 }
3354
3355#ifdef F_DUPFD_CLOEXEC
3356 if (!cloexec_done)
3357#endif
3358 {
3360 }
3361
3362 return new_fd;
3363}
3364
3374 DBusError *error)
3375{
3376 return _dbus_set_fd_nonblocking (fd.fd, error);
3377}
3378
3379static dbus_bool_t
3380_dbus_set_fd_nonblocking (int fd,
3381 DBusError *error)
3382{
3383 int val;
3384
3385 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3386
3387 val = fcntl (fd, F_GETFL, 0);
3388 if (val < 0)
3389 {
3390 dbus_set_error (error, _dbus_error_from_errno (errno),
3391 "Failed to get flags from file descriptor %d: %s",
3392 fd, _dbus_strerror (errno));
3393 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3394 _dbus_strerror (errno));
3395 return FALSE;
3396 }
3397
3398 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3399 {
3400 dbus_set_error (error, _dbus_error_from_errno (errno),
3401 "Failed to set nonblocking flag of file descriptor %d: %s",
3402 fd, _dbus_strerror (errno));
3403 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3404 fd, _dbus_strerror (errno));
3405
3406 return FALSE;
3407 }
3408
3409 return TRUE;
3410}
3411
3417void
3419{
3420#if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3421 void *bt[500];
3422 int bt_size;
3423 int i;
3424 char **syms;
3425
3426 bt_size = backtrace (bt, 500);
3427
3428 syms = backtrace_symbols (bt, bt_size);
3429
3430 i = 0;
3431 while (i < bt_size)
3432 {
3433 /* don't use dbus_warn since it can _dbus_abort() */
3434 fprintf (stderr, " %s\n", syms[i]);
3435 ++i;
3436 }
3437 fflush (stderr);
3438
3439 free (syms);
3440#elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3441 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3442#else
3443 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3444#endif
3445}
3446
3461 DBusSocket *fd2,
3462 dbus_bool_t blocking,
3463 DBusError *error)
3464{
3465#ifdef HAVE_SOCKETPAIR
3466 int fds[2];
3467 int retval;
3468
3469#ifdef SOCK_CLOEXEC
3470 dbus_bool_t cloexec_done;
3471
3472 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3473 cloexec_done = retval >= 0;
3474
3475 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3476#endif
3477 {
3478 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3479 }
3480
3481 if (retval < 0)
3482 {
3483 dbus_set_error (error, _dbus_error_from_errno (errno),
3484 "Could not create full-duplex pipe");
3485 return FALSE;
3486 }
3487
3488 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3489
3490#ifdef SOCK_CLOEXEC
3491 if (!cloexec_done)
3492#endif
3493 {
3496 }
3497
3498 if (!blocking &&
3499 (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3500 !_dbus_set_fd_nonblocking (fds[1], NULL)))
3501 {
3502 dbus_set_error (error, _dbus_error_from_errno (errno),
3503 "Could not set full-duplex pipe nonblocking");
3504
3505 _dbus_close (fds[0], NULL);
3506 _dbus_close (fds[1], NULL);
3507
3508 return FALSE;
3509 }
3510
3511 fd1->fd = fds[0];
3512 fd2->fd = fds[1];
3513
3514 _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3515 fd1->fd, fd2->fd);
3516
3517 return TRUE;
3518#else
3519 _dbus_warn ("_dbus_socketpair() not implemented on this OS");
3521 "_dbus_socketpair() not implemented on this OS");
3522 return FALSE;
3523#endif
3524}
3525
3534int
3536 va_list args)
3537{
3538 char static_buf[1024];
3539 int bufsize = sizeof (static_buf);
3540 int len;
3541 va_list args_copy;
3542
3543 DBUS_VA_COPY (args_copy, args);
3544 len = vsnprintf (static_buf, bufsize, format, args_copy);
3545 va_end (args_copy);
3546
3547 /* If vsnprintf() returned non-negative, then either the string fits in
3548 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3549 * returns the number of characters that were needed, or this OS returns the
3550 * truncated length.
3551 *
3552 * We ignore the possibility that snprintf might just ignore the length and
3553 * overrun the buffer (64-bit Solaris 7), because that's pathological.
3554 * If your libc is really that bad, come back when you have a better one. */
3555 if (len == bufsize)
3556 {
3557 /* This could be the truncated length (Tru64 and IRIX have this bug),
3558 * or the real length could be coincidentally the same. Which is it?
3559 * If vsnprintf returns the truncated length, we'll go to the slow
3560 * path. */
3561 DBUS_VA_COPY (args_copy, args);
3562
3563 if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3564 len = -1;
3565
3566 va_end (args_copy);
3567 }
3568
3569 /* If vsnprintf() returned negative, we have to do more work.
3570 * HP-UX returns negative. */
3571 while (len < 0)
3572 {
3573 char *buf;
3574
3575 bufsize *= 2;
3576
3577 buf = dbus_malloc (bufsize);
3578
3579 if (buf == NULL)
3580 return -1;
3581
3582 DBUS_VA_COPY (args_copy, args);
3583 len = vsnprintf (buf, bufsize, format, args_copy);
3584 va_end (args_copy);
3585
3586 dbus_free (buf);
3587
3588 /* If the reported length is exactly the buffer size, round up to the
3589 * next size, in case vsnprintf has been returning the truncated
3590 * length */
3591 if (len == bufsize)
3592 len = -1;
3593 }
3594
3595 return len;
3596}
3597
3604const char*
3606{
3607 /* Protected by _DBUS_LOCK_sysdeps */
3608 static const char* tmpdir = NULL;
3609
3610 if (!_DBUS_LOCK (sysdeps))
3611 return NULL;
3612
3613 if (tmpdir == NULL)
3614 {
3615 /* TMPDIR is what glibc uses, then
3616 * glibc falls back to the P_tmpdir macro which
3617 * just expands to "/tmp"
3618 */
3619 if (tmpdir == NULL)
3620 tmpdir = getenv("TMPDIR");
3621
3622 /* These two env variables are probably
3623 * broken, but maybe some OS uses them?
3624 */
3625 if (tmpdir == NULL)
3626 tmpdir = getenv("TMP");
3627 if (tmpdir == NULL)
3628 tmpdir = getenv("TEMP");
3629
3630 /* And this is the sane fallback. */
3631 if (tmpdir == NULL)
3632 tmpdir = "/tmp";
3633 }
3634
3635 _DBUS_UNLOCK (sysdeps);
3636
3637 _dbus_assert(tmpdir != NULL);
3638
3639 return tmpdir;
3640}
3641
3642#if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3662static dbus_bool_t
3663_read_subprocess_line_argv (const char *progpath,
3664 dbus_bool_t path_fallback,
3665 const char * const *argv,
3666 DBusString *result,
3667 DBusError *error)
3668{
3669 int result_pipe[2] = { -1, -1 };
3670 int errors_pipe[2] = { -1, -1 };
3671 pid_t pid;
3672 int ret;
3673 int status;
3674 int orig_len;
3675
3676 dbus_bool_t retval;
3677 sigset_t new_set, old_set;
3678
3679 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3680 retval = FALSE;
3681
3682 /* We need to block any existing handlers for SIGCHLD temporarily; they
3683 * will cause waitpid() below to fail.
3684 * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3685 */
3686 sigemptyset (&new_set);
3687 sigaddset (&new_set, SIGCHLD);
3688 sigprocmask (SIG_BLOCK, &new_set, &old_set);
3689
3690 orig_len = _dbus_string_get_length (result);
3691
3692#define READ_END 0
3693#define WRITE_END 1
3694 if (pipe (result_pipe) < 0)
3695 {
3696 dbus_set_error (error, _dbus_error_from_errno (errno),
3697 "Failed to create a pipe to call %s: %s",
3698 progpath, _dbus_strerror (errno));
3699 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3700 progpath, _dbus_strerror (errno));
3701 goto out;
3702 }
3703 if (pipe (errors_pipe) < 0)
3704 {
3705 dbus_set_error (error, _dbus_error_from_errno (errno),
3706 "Failed to create a pipe to call %s: %s",
3707 progpath, _dbus_strerror (errno));
3708 _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3709 progpath, _dbus_strerror (errno));
3710 goto out;
3711 }
3712
3713 pid = fork ();
3714 if (pid < 0)
3715 {
3716 dbus_set_error (error, _dbus_error_from_errno (errno),
3717 "Failed to fork() to call %s: %s",
3718 progpath, _dbus_strerror (errno));
3719 _dbus_verbose ("Failed to fork() to call %s: %s\n",
3720 progpath, _dbus_strerror (errno));
3721 goto out;
3722 }
3723
3724 if (pid == 0)
3725 {
3726 /* child process */
3727 const char *error_str;
3728
3729 if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
3730 {
3731 int saved_errno = errno;
3732
3733 /* Try to write details into the pipe, but don't bother
3734 * trying too hard (no retry loop). */
3735
3736 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0 ||
3737 write (errors_pipe[WRITE_END], ": ", 2) < 0)
3738 {
3739 /* ignore, not much we can do */
3740 }
3741
3742 error_str = _dbus_strerror (saved_errno);
3743
3744 if (write (errors_pipe[WRITE_END], error_str, strlen (error_str)) < 0)
3745 {
3746 /* ignore, not much we can do */
3747 }
3748
3749 _exit (1);
3750 }
3751
3752 /* set-up stdXXX */
3753 close (result_pipe[READ_END]);
3754 close (errors_pipe[READ_END]);
3755
3756 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3757 _exit (1);
3758 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3759 _exit (1);
3760
3761 _dbus_close_all ();
3762
3763 sigprocmask (SIG_SETMASK, &old_set, NULL);
3764
3765 /* If it looks fully-qualified, try execv first */
3766 if (progpath[0] == '/')
3767 {
3768 execv (progpath, (char * const *) argv);
3769 /* Ok, that failed. Now if path_fallback is given, let's
3770 * try unqualified. This is mostly a hack to work
3771 * around systems which ship dbus-launch in /usr/bin
3772 * but everything else in /bin (because dbus-launch
3773 * depends on X11).
3774 */
3775 if (path_fallback)
3776 /* We must have a slash, because we checked above */
3777 execvp (strrchr (progpath, '/')+1, (char * const *) argv);
3778 }
3779 else
3780 execvp (progpath, (char * const *) argv);
3781
3782 /* still nothing, we failed */
3783 _exit (1);
3784 }
3785
3786 /* parent process */
3787 close (result_pipe[WRITE_END]);
3788 close (errors_pipe[WRITE_END]);
3789 result_pipe[WRITE_END] = -1;
3790 errors_pipe[WRITE_END] = -1;
3791
3792 ret = 0;
3793 do
3794 {
3795 ret = _dbus_read (result_pipe[READ_END], result, 1024);
3796 }
3797 while (ret > 0);
3798
3799 /* reap the child process to avoid it lingering as zombie */
3800 do
3801 {
3802 ret = waitpid (pid, &status, 0);
3803 }
3804 while (ret == -1 && errno == EINTR);
3805
3806 /* We succeeded if the process exited with status 0 and
3807 anything was read */
3808 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3809 {
3810 /* The process ended with error */
3811 DBusString error_message;
3812 if (!_dbus_string_init (&error_message))
3813 {
3814 _DBUS_SET_OOM (error);
3815 goto out;
3816 }
3817
3818 ret = 0;
3819 do
3820 {
3821 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3822 }
3823 while (ret > 0);
3824
3825 _dbus_string_set_length (result, orig_len);
3826 if (_dbus_string_get_length (&error_message) > 0)
3828 "%s terminated abnormally with the following error: %s",
3829 progpath, _dbus_string_get_data (&error_message));
3830 else
3832 "%s terminated abnormally without any error message",
3833 progpath);
3834 goto out;
3835 }
3836
3837 retval = TRUE;
3838
3839 out:
3840 sigprocmask (SIG_SETMASK, &old_set, NULL);
3841
3842 if (retval)
3843 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3844 else
3845 _DBUS_ASSERT_ERROR_IS_SET (error);
3846
3847 if (result_pipe[0] != -1)
3848 close (result_pipe[0]);
3849 if (result_pipe[1] != -1)
3850 close (result_pipe[1]);
3851 if (errors_pipe[0] != -1)
3852 close (errors_pipe[0]);
3853 if (errors_pipe[1] != -1)
3854 close (errors_pipe[1]);
3855
3856 return retval;
3857}
3858#endif
3859
3874 DBusString *address,
3875 DBusError *error)
3876{
3877#ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3878 static const char arg_dbus_launch[] = "dbus-launch";
3879 static const char arg_autolaunch[] = "--autolaunch";
3880 static const char arg_binary_syntax[] = "--binary-syntax";
3881 static const char arg_close_stderr[] = "--close-stderr";
3882
3883 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3884 * but that's done elsewhere, and if it worked, this function wouldn't
3885 * be called.) */
3886 const char *display;
3887 const char *progpath;
3888 const char *argv[6];
3889 int i;
3890 DBusString uuid;
3891 dbus_bool_t retval;
3892
3893 if (_dbus_check_setuid ())
3894 {
3896 "Unable to autolaunch when setuid");
3897 return FALSE;
3898 }
3899
3900 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3901 retval = FALSE;
3902
3903 /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3904 * dbus-launch-x11 is just going to fail. Rather than trying to
3905 * run it, we might as well bail out early with a nice error.
3906 *
3907 * This is not strictly true in a world where the user bus exists,
3908 * because dbus-launch --autolaunch knows how to connect to that -
3909 * but if we were going to connect to the user bus, we'd have done
3910 * so before trying autolaunch: in any case. */
3911 display = _dbus_getenv ("DISPLAY");
3912
3913 if (display == NULL || display[0] == '\0')
3914 {
3916 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3917 return FALSE;
3918 }
3919
3920 if (!_dbus_string_init (&uuid))
3921 {
3922 _DBUS_SET_OOM (error);
3923 return FALSE;
3924 }
3925
3926 if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3927 {
3928 goto out;
3929 }
3930
3931#ifdef DBUS_ENABLE_EMBEDDED_TESTS
3932 progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3933
3934 if (progpath == NULL)
3935#endif
3936 progpath = DBUS_BINDIR "/dbus-launch";
3937 /*
3938 * argv[0] is always dbus-launch, that's the name what we'll
3939 * get from /proc, or ps(1), regardless what the progpath is,
3940 * see fd.o#69716
3941 */
3942 i = 0;
3943 argv[i] = arg_dbus_launch;
3944 ++i;
3945 argv[i] = arg_autolaunch;
3946 ++i;
3947 argv[i] = _dbus_string_get_data (&uuid);
3948 ++i;
3949 argv[i] = arg_binary_syntax;
3950 ++i;
3951 argv[i] = arg_close_stderr;
3952 ++i;
3953 argv[i] = NULL;
3954 ++i;
3955
3956 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3957
3958 retval = _read_subprocess_line_argv (progpath,
3959 TRUE,
3960 argv, address, error);
3961
3962 out:
3963 _dbus_string_free (&uuid);
3964 return retval;
3965#else
3967 "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3968 "set your DBUS_SESSION_BUS_ADDRESS instead");
3969 return FALSE;
3970#endif
3971}
3972
3993 dbus_bool_t create_if_not_found,
3994 DBusError *error)
3995{
3996 DBusError our_error = DBUS_ERROR_INIT;
3997 DBusError etc_error = DBUS_ERROR_INIT;
3998 DBusString filename;
3999 dbus_bool_t b;
4000
4001 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4002
4003 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &our_error);
4004 if (b)
4005 return TRUE;
4006
4007 /* Fallback to the system machine ID */
4008 _dbus_string_init_const (&filename, "/etc/machine-id");
4009 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, &etc_error);
4010
4011 if (b)
4012 {
4013 if (create_if_not_found)
4014 {
4015 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
4016 * complain if that isn't possible for whatever reason */
4017 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4018 _dbus_write_uuid_file (&filename, machine_id, NULL);
4019 }
4020
4021 dbus_error_free (&our_error);
4022 return TRUE;
4023 }
4024
4025 if (!create_if_not_found)
4026 {
4027 dbus_set_error (error, etc_error.name,
4028 "D-Bus library appears to be incorrectly set up: "
4029 "see the manual page for dbus-uuidgen to correct "
4030 "this issue. (%s; %s)",
4031 our_error.message, etc_error.message);
4032 dbus_error_free (&our_error);
4033 dbus_error_free (&etc_error);
4034 return FALSE;
4035 }
4036
4037 dbus_error_free (&our_error);
4038 dbus_error_free (&etc_error);
4039
4040 /* if none found, try to make a new one */
4041 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
4042
4043 if (!_dbus_generate_uuid (machine_id, error))
4044 return FALSE;
4045
4046 return _dbus_write_uuid_file (&filename, machine_id, error);
4047}
4048
4058 const char *launchd_env_var,
4059 DBusError *error)
4060{
4061#ifdef DBUS_ENABLE_LAUNCHD
4062 char *argv[4];
4063 int i;
4064
4065 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4066
4067 if (_dbus_check_setuid ())
4068 {
4070 "Unable to find launchd socket when setuid");
4071 return FALSE;
4072 }
4073
4074 i = 0;
4075 argv[i] = "launchctl";
4076 ++i;
4077 argv[i] = "getenv";
4078 ++i;
4079 argv[i] = (char*)launchd_env_var;
4080 ++i;
4081 argv[i] = NULL;
4082 ++i;
4083
4084 _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
4085
4086 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
4087 {
4088 return FALSE;
4089 }
4090
4091 /* no error, but no result either */
4092 if (_dbus_string_get_length(socket_path) == 0)
4093 {
4094 return FALSE;
4095 }
4096
4097 /* strip the carriage-return */
4098 _dbus_string_shorten(socket_path, 1);
4099 return TRUE;
4100#else /* DBUS_ENABLE_LAUNCHD */
4102 "can't lookup socket from launchd; launchd support not compiled in");
4103 return FALSE;
4104#endif
4105}
4106
4107#ifdef DBUS_ENABLE_LAUNCHD
4108static dbus_bool_t
4109_dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
4110{
4111 dbus_bool_t valid_socket;
4112 DBusString socket_path;
4113
4114 if (_dbus_check_setuid ())
4115 {
4117 "Unable to find launchd socket when setuid");
4118 return FALSE;
4119 }
4120
4121 if (!_dbus_string_init (&socket_path))
4122 {
4123 _DBUS_SET_OOM (error);
4124 return FALSE;
4125 }
4126
4127 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4128
4129 if (dbus_error_is_set(error))
4130 {
4131 _dbus_string_free(&socket_path);
4132 return FALSE;
4133 }
4134
4135 if (!valid_socket)
4136 {
4137 dbus_set_error(error, "no socket path",
4138 "launchd did not provide a socket path, "
4139 "verify that org.freedesktop.dbus-session.plist is loaded!");
4140 _dbus_string_free(&socket_path);
4141 return FALSE;
4142 }
4143 if (!_dbus_string_append (address, "unix:path="))
4144 {
4145 _DBUS_SET_OOM (error);
4146 _dbus_string_free(&socket_path);
4147 return FALSE;
4148 }
4149 if (!_dbus_string_copy (&socket_path, 0, address,
4150 _dbus_string_get_length (address)))
4151 {
4152 _DBUS_SET_OOM (error);
4153 _dbus_string_free(&socket_path);
4154 return FALSE;
4155 }
4156
4157 _dbus_string_free(&socket_path);
4158 return TRUE;
4159}
4160#endif
4161
4163_dbus_lookup_user_bus (dbus_bool_t *supported,
4164 DBusString *address,
4165 DBusError *error)
4166{
4167 const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4168 dbus_bool_t ret = FALSE;
4169 struct stat stbuf;
4170 DBusString user_bus_path;
4171
4172 if (runtime_dir == NULL)
4173 {
4174 _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4175 *supported = FALSE;
4176 return TRUE; /* Cannot use it, but not an error */
4177 }
4178
4179 if (!_dbus_string_init (&user_bus_path))
4180 {
4181 _DBUS_SET_OOM (error);
4182 return FALSE;
4183 }
4184
4185 if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4186 {
4187 _DBUS_SET_OOM (error);
4188 goto out;
4189 }
4190
4191 if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4192 {
4193 _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4194 _dbus_strerror (errno));
4195 *supported = FALSE;
4196 ret = TRUE; /* Cannot use it, but not an error */
4197 goto out;
4198 }
4199
4200 if (stbuf.st_uid != getuid ())
4201 {
4202 _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4203 (long) stbuf.st_uid, (long) getuid ());
4204 *supported = FALSE;
4205 ret = TRUE; /* Cannot use it, but not an error */
4206 goto out;
4207 }
4208
4209 if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4210 {
4211 _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4212 (long) stbuf.st_mode);
4213 *supported = FALSE;
4214 ret = TRUE; /* Cannot use it, but not an error */
4215 goto out;
4216 }
4217
4218 if (!_dbus_string_append (address, "unix:path=") ||
4219 !_dbus_address_append_escaped (address, &user_bus_path))
4220 {
4221 _DBUS_SET_OOM (error);
4222 goto out;
4223 }
4224
4225 *supported = TRUE;
4226 ret = TRUE;
4227
4228out:
4229 _dbus_string_free (&user_bus_path);
4230 return ret;
4231}
4232
4254 DBusString *address,
4255 DBusError *error)
4256{
4257#ifdef DBUS_ENABLE_LAUNCHD
4258 *supported = TRUE;
4259 return _dbus_lookup_session_address_launchd (address, error);
4260#else
4261 *supported = FALSE;
4262
4263 if (!_dbus_lookup_user_bus (supported, address, error))
4264 return FALSE;
4265 else if (*supported)
4266 return TRUE;
4267
4268 /* On non-Mac Unix platforms, if the session address isn't already
4269 * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4270 * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4271 * autolaunch: global default; see init_session_address in
4272 * dbus/dbus-bus.c. */
4273 return TRUE;
4274#endif
4275}
4276
4284void
4286{
4288}
4289
4305 DBusCredentials *credentials)
4306{
4307 DBusString homedir;
4308 DBusString dotdir;
4309 dbus_uid_t uid;
4310
4311 _dbus_assert (credentials != NULL);
4313
4314 if (!_dbus_string_init (&homedir))
4315 return FALSE;
4316
4317 uid = _dbus_credentials_get_unix_uid (credentials);
4319
4320 if (!_dbus_homedir_from_uid (uid, &homedir))
4321 goto failed;
4322
4323#ifdef DBUS_ENABLE_EMBEDDED_TESTS
4324 {
4325 const char *override;
4326
4327 override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4328 if (override != NULL && *override != '\0')
4329 {
4330 _dbus_string_set_length (&homedir, 0);
4331 if (!_dbus_string_append (&homedir, override))
4332 goto failed;
4333
4334 _dbus_verbose ("Using fake homedir for testing: %s\n",
4335 _dbus_string_get_const_data (&homedir));
4336 }
4337 else
4338 {
4339 /* Not strictly thread-safe, but if we fail at thread-safety here,
4340 * the worst that will happen is some extra warnings. */
4341 static dbus_bool_t already_warned = FALSE;
4342 if (!already_warned)
4343 {
4344 _dbus_warn ("Using %s for testing, set DBUS_TEST_HOMEDIR to avoid",
4345 _dbus_string_get_const_data (&homedir));
4346 already_warned = TRUE;
4347 }
4348 }
4349 }
4350#endif
4351
4352 _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4353 if (!_dbus_concat_dir_and_file (&homedir,
4354 &dotdir))
4355 goto failed;
4356
4357 if (!_dbus_string_copy (&homedir, 0,
4358 directory, _dbus_string_get_length (directory))) {
4359 goto failed;
4360 }
4361
4362 _dbus_string_free (&homedir);
4363 return TRUE;
4364
4365 failed:
4366 _dbus_string_free (&homedir);
4367 return FALSE;
4368}
4369
4370//PENDING(kdab) docs
4372_dbus_daemon_publish_session_bus_address (const char* addr,
4373 const char *scope)
4374{
4375 return TRUE;
4376}
4377
4378//PENDING(kdab) docs
4379void
4380_dbus_daemon_unpublish_session_bus_address (void)
4381{
4382
4383}
4384
4393{
4394 /* Avoid the -Wlogical-op GCC warning, which can be triggered when EAGAIN and
4395 * EWOULDBLOCK are numerically equal, which is permitted as described by
4396 * errno(3).
4397 */
4398#if EAGAIN == EWOULDBLOCK
4399 return e == EAGAIN;
4400#else
4401 return e == EAGAIN || e == EWOULDBLOCK;
4402#endif
4403}
4404
4414 DBusError *error)
4415{
4416 const char *filename_c;
4417
4418 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4419
4420 filename_c = _dbus_string_get_const_data (filename);
4421
4422 if (rmdir (filename_c) != 0)
4423 {
4425 "Failed to remove directory %s: %s\n",
4426 filename_c, _dbus_strerror (errno));
4427 return FALSE;
4428 }
4429
4430 return TRUE;
4431}
4432
4442{
4443#ifdef SCM_RIGHTS
4444 union {
4445 struct sockaddr sa;
4446 struct sockaddr_storage storage;
4447 struct sockaddr_un un;
4448 } sa_buf;
4449
4450 socklen_t sa_len = sizeof(sa_buf);
4451
4452 _DBUS_ZERO(sa_buf);
4453
4454 if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4455 return FALSE;
4456
4457 return sa_buf.sa.sa_family == AF_UNIX;
4458
4459#else
4460 return FALSE;
4461
4462#endif
4463}
4464
4469void
4471{
4472 int maxfds, i;
4473
4474#ifdef __linux__
4475 DIR *d;
4476
4477 /* On Linux we can optimize this a bit if /proc is available. If it
4478 isn't available, fall back to the brute force way. */
4479
4480 d = opendir ("/proc/self/fd");
4481 if (d)
4482 {
4483 for (;;)
4484 {
4485 struct dirent *de;
4486 int fd;
4487 long l;
4488 char *e = NULL;
4489
4490 de = readdir (d);
4491 if (!de)
4492 break;
4493
4494 if (de->d_name[0] == '.')
4495 continue;
4496
4497 errno = 0;
4498 l = strtol (de->d_name, &e, 10);
4499 if (errno != 0 || e == NULL || *e != '\0')
4500 continue;
4501
4502 fd = (int) l;
4503 if (fd < 3)
4504 continue;
4505
4506 if (fd == dirfd (d))
4507 continue;
4508
4509 close (fd);
4510 }
4511
4512 closedir (d);
4513 return;
4514 }
4515#endif
4516
4517 maxfds = sysconf (_SC_OPEN_MAX);
4518
4519 /* Pick something reasonable if for some reason sysconf says
4520 * unlimited.
4521 */
4522 if (maxfds < 0)
4523 maxfds = 1024;
4524
4525 /* close all inherited fds */
4526 for (i = 3; i < maxfds; i++)
4527 close (i);
4528}
4529
4541{
4542 /* TODO: get __libc_enable_secure exported from glibc.
4543 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4544 */
4545#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4546 {
4547 /* See glibc/include/unistd.h */
4548 extern int __libc_enable_secure;
4549 return __libc_enable_secure;
4550 }
4551#elif defined(HAVE_ISSETUGID)
4552 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4553 return issetugid ();
4554#else
4555 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4556 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4557
4558 /* We call into this function from _dbus_threads_init_platform_specific()
4559 * to make sure these are initialized before we start threading. */
4560 static dbus_bool_t check_setuid_initialised;
4561 static dbus_bool_t is_setuid;
4562
4563 if (_DBUS_UNLIKELY (!check_setuid_initialised))
4564 {
4565#ifdef HAVE_GETRESUID
4566 if (getresuid (&ruid, &euid, &suid) != 0 ||
4567 getresgid (&rgid, &egid, &sgid) != 0)
4568#endif /* HAVE_GETRESUID */
4569 {
4570 suid = ruid = getuid ();
4571 sgid = rgid = getgid ();
4572 euid = geteuid ();
4573 egid = getegid ();
4574 }
4575
4576 check_setuid_initialised = TRUE;
4577 is_setuid = (ruid != euid || ruid != suid ||
4578 rgid != egid || rgid != sgid);
4579
4580 }
4581 return is_setuid;
4582#endif
4583}
4584
4594 DBusString *address,
4595 DBusError *error)
4596{
4597 union {
4598 struct sockaddr sa;
4599 struct sockaddr_storage storage;
4600 struct sockaddr_un un;
4601 struct sockaddr_in ipv4;
4602 struct sockaddr_in6 ipv6;
4603 } socket;
4604 char hostip[INET6_ADDRSTRLEN];
4605 socklen_t size = sizeof (socket);
4606 DBusString path_str;
4607
4608 if (getsockname (fd.fd, &socket.sa, &size))
4609 goto err;
4610
4611 switch (socket.sa.sa_family)
4612 {
4613 case AF_UNIX:
4614 if (socket.un.sun_path[0]=='\0')
4615 {
4616 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4617 if (_dbus_string_append (address, "unix:abstract=") &&
4618 _dbus_address_append_escaped (address, &path_str))
4619 return TRUE;
4620 }
4621 else
4622 {
4623 _dbus_string_init_const (&path_str, socket.un.sun_path);
4624 if (_dbus_string_append (address, "unix:path=") &&
4625 _dbus_address_append_escaped (address, &path_str))
4626 return TRUE;
4627 }
4628 break;
4629 case AF_INET:
4630 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4631 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4632 hostip, ntohs (socket.ipv4.sin_port)))
4633 return TRUE;
4634 break;
4635#ifdef AF_INET6
4636 case AF_INET6:
4637 _dbus_string_init_const (&path_str, hostip);
4638 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4639 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4640 ntohs (socket.ipv6.sin6_port)) &&
4641 _dbus_address_append_escaped (address, &path_str))
4642 return TRUE;
4643 break;
4644#endif
4645 default:
4646 dbus_set_error (error,
4647 _dbus_error_from_errno (EINVAL),
4648 "Failed to read address from socket: Unknown socket type.");
4649 return FALSE;
4650 }
4651 err:
4652 dbus_set_error (error,
4653 _dbus_error_from_errno (errno),
4654 "Failed to open socket: %s",
4655 _dbus_strerror (errno));
4656 return FALSE;
4657}
4658
4659int
4660_dbus_save_socket_errno (void)
4661{
4662 return errno;
4663}
4664
4665void
4666_dbus_restore_socket_errno (int saved_errno)
4667{
4668 errno = saved_errno;
4669}
4670
4671static const char *syslog_tag = "dbus";
4672#ifdef HAVE_SYSLOG_H
4673static DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
4674#endif
4675
4690void
4691_dbus_init_system_log (const char *tag,
4692 DBusLogFlags flags)
4693{
4694 /* We never want to turn off logging completely */
4695 _dbus_assert (
4696 (flags & (DBUS_LOG_FLAGS_STDERR | DBUS_LOG_FLAGS_SYSTEM_LOG)) != 0);
4697
4698 syslog_tag = tag;
4699
4700#ifdef HAVE_SYSLOG_H
4701 log_flags = flags;
4702
4703 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4704 openlog (tag, LOG_PID, LOG_DAEMON);
4705#endif
4706}
4707
4715void
4716_dbus_logv (DBusSystemLogSeverity severity,
4717 const char *msg,
4718 va_list args)
4719{
4720 va_list tmp;
4721#ifdef HAVE_SYSLOG_H
4722 if (log_flags & DBUS_LOG_FLAGS_SYSTEM_LOG)
4723 {
4724 int flags;
4725 switch (severity)
4726 {
4727 case DBUS_SYSTEM_LOG_INFO:
4728 flags = LOG_DAEMON | LOG_INFO;
4729 break;
4730 case DBUS_SYSTEM_LOG_WARNING:
4731 flags = LOG_DAEMON | LOG_WARNING;
4732 break;
4733 case DBUS_SYSTEM_LOG_SECURITY:
4734 flags = LOG_AUTH | LOG_NOTICE;
4735 break;
4736 case DBUS_SYSTEM_LOG_ERROR:
4737 flags = LOG_DAEMON|LOG_CRIT;
4738 break;
4739 default:
4740 _dbus_assert_not_reached ("invalid log severity");
4741 }
4742
4743 DBUS_VA_COPY (tmp, args);
4744 vsyslog (flags, msg, tmp);
4745 va_end (tmp);
4746 }
4747
4748 /* If we don't have syslog.h, we always behave as though stderr was in
4749 * the flags */
4750 if (log_flags & DBUS_LOG_FLAGS_STDERR)
4751#endif
4752 {
4753 DBUS_VA_COPY (tmp, args);
4754 fprintf (stderr, "%s[" DBUS_PID_FORMAT "]: ", syslog_tag, _dbus_getpid ());
4755 vfprintf (stderr, msg, tmp);
4756 fputc ('\n', stderr);
4757 va_end (tmp);
4758 }
4759}
4760
4761/* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_address_append_escaped(DBusString *escaped, const DBusString *unescaped)
Appends an escaped version of one string to another string, using the D-Bus address escaping mechanis...
Definition: dbus-address.c:104
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.
Definition: dbus-errors.c:243
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define READ_END
Helps remember which end of the pipe is which.
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.
Definition: dbus-sysdeps.c:592
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:386
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
dbus_bool_t _dbus_homedir_from_uid(dbus_uid_t uid, DBusString *homedir)
Gets the home directory for the given user.
Definition: dbus-userdb.c:498
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++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:602
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:462
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:935
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1283
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:132
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:490
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
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.
Definition: dbus-sysdeps.c:437
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:394
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1157
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1114
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.
Definition: dbus-sysdeps.h:409
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:134
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted)
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:132
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
void _dbus_exit(int code)
Exit the process, returning the given value.
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:411
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.
Definition: dbus-sysdeps.h:136
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, unsigned int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
dbus_bool_t _dbus_append_keyring_directory_for_credentials(DBusString *directory, DBusCredentials *credentials)
Appends the directory in which a keyring for the given credentials should be stored.
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:141
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
dbus_bool_t _dbus_read_credentials_socket(DBusSocket client_fd, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:139
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket fd, DBusError *error)
Sets a file descriptor to be nonblocking.
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib.
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:143
dbus_bool_t _dbus_check_dir_is_private_to_user(DBusString *dir, DBusError *error)
Checks to make sure the given directory is private to the user.
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:405
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
Definition: dbus-sysdeps.h:150
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
dbus_bool_t _dbus_delete_directory(const DBusString *filename, DBusError *error)
Removes a directory; Directory must be empty.
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:148
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
Definition: dbus-sysdeps.h:146
dbus_bool_t _dbus_ensure_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:307
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:311
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.
Definition: dbus-sysdeps.h:400
short revents
Events that occurred.
Definition: dbus-sysdeps.h:401
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:399
Socket interface.
Definition: dbus-sysdeps.h:175
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...