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