D-Bus  1.10.28
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_WRITEV
66 #include <sys/uio.h>
67 #endif
68 #ifdef HAVE_POLL
69 #include <sys/poll.h>
70 #endif
71 #ifdef HAVE_BACKTRACE
72 #include <execinfo.h>
73 #endif
74 #ifdef HAVE_GETPEERUCRED
75 #include <ucred.h>
76 #endif
77 #ifdef HAVE_ALLOCA_H
78 #include <alloca.h>
79 #endif
80 
81 #ifdef HAVE_ADT
82 #include <bsm/adt.h>
83 #endif
84 
85 #ifdef HAVE_SYSTEMD
86 #include <systemd/sd-daemon.h>
87 #endif
88 
89 #if !DBUS_USE_SYNC
90 #include <pthread.h>
91 #endif
92 
93 #ifndef O_BINARY
94 #define O_BINARY 0
95 #endif
96 
97 #ifndef AI_ADDRCONFIG
98 #define AI_ADDRCONFIG 0
99 #endif
100 
101 #ifndef HAVE_SOCKLEN_T
102 #define socklen_t int
103 #endif
104 
105 #if defined (__sun) || defined (__sun__)
106 /*
107  * CMS_SPACE etc. definitions for Solaris < 10, based on
108  * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
109  * via
110  * http://wiki.opencsw.org/porting-faq#toc10
111  *
112  * These are only redefined for Solaris, for now: if your OS needs these too,
113  * please file a bug. (Or preferably, improve your OS so they're not needed.)
114  */
115 
116 # ifndef CMSG_ALIGN
117 # ifdef __sun__
118 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
119 # else
120  /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
121 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
122  ~(sizeof (long) - 1))
123 # endif
124 # endif
125 
126 # ifndef CMSG_SPACE
127 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
128  CMSG_ALIGN (len))
129 # endif
130 
131 # ifndef CMSG_LEN
132 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
133 # endif
134 
135 #endif /* Solaris */
136 
152 _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags,
153  const char **error_str_p)
154 {
155  static int const relevant_flag[] = { DBUS_FORCE_STDIN_NULL,
156  DBUS_FORCE_STDOUT_NULL,
157  DBUS_FORCE_STDERR_NULL };
158  /* Should always get replaced with the real error before use */
159  const char *error_str = "Failed mysteriously";
160  int devnull = -1;
161  int saved_errno;
162  /* This function relies on the standard fds having their POSIX values. */
163  _DBUS_STATIC_ASSERT (STDIN_FILENO == 0);
164  _DBUS_STATIC_ASSERT (STDOUT_FILENO == 1);
165  _DBUS_STATIC_ASSERT (STDERR_FILENO == 2);
166  int i;
167 
168  for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
169  {
170  /* Because we rely on being single-threaded, and we want the
171  * standard fds to not be close-on-exec, we don't set it
172  * close-on-exec. */
173  if (devnull < i)
174  devnull = open ("/dev/null", O_RDWR);
175 
176  if (devnull < 0)
177  {
178  error_str = "Failed to open /dev/null";
179  goto out;
180  }
181 
182  /* We already opened all fds < i, so the only way this assertion
183  * could fail is if another thread closed one, and we document
184  * this function as not safe for multi-threading. */
185  _dbus_assert (devnull >= i);
186 
187  if (devnull != i && (flags & relevant_flag[i]) != 0)
188  {
189  if (dup2 (devnull, i) < 0)
190  {
191  error_str = "Failed to dup2 /dev/null onto a standard fd";
192  goto out;
193  }
194  }
195  }
196 
197  error_str = NULL;
198 
199 out:
200  saved_errno = errno;
201 
202  if (devnull > STDERR_FILENO)
203  close (devnull);
204 
205  if (error_str_p != NULL)
206  *error_str_p = error_str;
207 
208  errno = saved_errno;
209  return (error_str == NULL);
210 }
211 
212 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
213  DBusError *error);
214 
215 static dbus_bool_t
216 _dbus_open_socket (int *fd_p,
217  int domain,
218  int type,
219  int protocol,
220  DBusError *error)
221 {
222 #ifdef SOCK_CLOEXEC
223  dbus_bool_t cloexec_done;
224 
225  *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
226  cloexec_done = *fd_p >= 0;
227 
228  /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
229  if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
230 #endif
231  {
232  *fd_p = socket (domain, type, protocol);
233  }
234 
235  if (*fd_p >= 0)
236  {
237 #ifdef SOCK_CLOEXEC
238  if (!cloexec_done)
239 #endif
240  {
242  }
243 
244  _dbus_verbose ("socket fd %d opened\n", *fd_p);
245  return TRUE;
246  }
247  else
248  {
249  dbus_set_error(error,
250  _dbus_error_from_errno (errno),
251  "Failed to open socket: %s",
252  _dbus_strerror (errno));
253  return FALSE;
254  }
255 }
256 
267 static dbus_bool_t
268 _dbus_open_unix_socket (int *fd,
269  DBusError *error)
270 {
271  return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
272 }
273 
284  DBusError *error)
285 {
286  return _dbus_close (fd.fd, error);
287 }
288 
298 int
300  DBusString *buffer,
301  int count)
302 {
303  return _dbus_read (fd.fd, buffer, count);
304 }
305 
316 int
318  const DBusString *buffer,
319  int start,
320  int len)
321 {
322 #if HAVE_DECL_MSG_NOSIGNAL
323  const char *data;
324  int bytes_written;
325 
326  data = _dbus_string_get_const_data_len (buffer, start, len);
327 
328  again:
329 
330  bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
331 
332  if (bytes_written < 0 && errno == EINTR)
333  goto again;
334 
335  return bytes_written;
336 
337 #else
338  return _dbus_write (fd.fd, buffer, start, len);
339 #endif
340 }
341 
354 int
356  DBusString *buffer,
357  int count,
358  int *fds,
359  int *n_fds) {
360 #ifndef HAVE_UNIX_FD_PASSING
361  int r;
362 
363  if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
364  return r;
365 
366  *n_fds = 0;
367  return r;
368 
369 #else
370  int bytes_read;
371  int start;
372  struct msghdr m;
373  struct iovec iov;
374 
375  _dbus_assert (count >= 0);
376  _dbus_assert (*n_fds >= 0);
377 
378  start = _dbus_string_get_length (buffer);
379 
380  if (!_dbus_string_lengthen (buffer, count))
381  {
382  errno = ENOMEM;
383  return -1;
384  }
385 
386  _DBUS_ZERO(iov);
387  iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
388  iov.iov_len = count;
389 
390  _DBUS_ZERO(m);
391  m.msg_iov = &iov;
392  m.msg_iovlen = 1;
393 
394  /* Hmm, we have no clue how long the control data will actually be
395  that is queued for us. The least we can do is assume that the
396  caller knows. Hence let's make space for the number of fds that
397  we shall read at max plus the cmsg header. */
398  m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
399 
400  /* It's probably safe to assume that systems with SCM_RIGHTS also
401  know alloca() */
402  m.msg_control = alloca(m.msg_controllen);
403  memset(m.msg_control, 0, m.msg_controllen);
404 
405  /* Do not include the padding at the end when we tell the kernel
406  * how much we're willing to receive. This avoids getting
407  * the padding filled with additional fds that we weren't expecting,
408  * if a (potentially malicious) sender included them. (fd.o #83622) */
409  m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
410 
411  again:
412 
413  bytes_read = recvmsg (fd.fd, &m, 0
414 #ifdef MSG_CMSG_CLOEXEC
415  |MSG_CMSG_CLOEXEC
416 #endif
417  );
418 
419  if (bytes_read < 0)
420  {
421  if (errno == EINTR)
422  goto again;
423  else
424  {
425  /* put length back (note that this doesn't actually realloc anything) */
426  _dbus_string_set_length (buffer, start);
427  return -1;
428  }
429  }
430  else
431  {
432  struct cmsghdr *cm;
433  dbus_bool_t found = FALSE;
434 
435  if (m.msg_flags & MSG_CTRUNC)
436  {
437  /* Hmm, apparently the control data was truncated. The bad
438  thing is that we might have completely lost a couple of fds
439  without chance to recover them. Hence let's treat this as a
440  serious error. */
441 
442  errno = ENOSPC;
443  _dbus_string_set_length (buffer, start);
444  return -1;
445  }
446 
447  for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
448  if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
449  {
450  size_t i;
451  int *payload = (int *) CMSG_DATA (cm);
452  size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
453  size_t payload_len_fds = payload_len_bytes / sizeof (int);
454  size_t fds_to_use;
455 
456  /* Every non-negative int fits in a size_t without truncation,
457  * and we already know that *n_fds is non-negative, so
458  * casting (size_t) *n_fds is OK */
459  _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
460 
461  if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
462  {
463  /* The fds in the payload will fit in our buffer */
464  fds_to_use = payload_len_fds;
465  }
466  else
467  {
468  /* Too many fds in the payload. This shouldn't happen
469  * any more because we're setting m.msg_controllen to
470  * the exact number we can accept, but be safe and
471  * truncate. */
472  fds_to_use = (size_t) *n_fds;
473 
474  /* Close the excess fds to avoid DoS: if they stayed open,
475  * someone could send us an extra fd per message
476  * and we'd eventually run out. */
477  for (i = fds_to_use; i < payload_len_fds; i++)
478  {
479  close (payload[i]);
480  }
481  }
482 
483  memcpy (fds, payload, fds_to_use * sizeof (int));
484  found = TRUE;
485  /* This cannot overflow because we have chosen fds_to_use
486  * to be <= *n_fds */
487  *n_fds = (int) fds_to_use;
488 
489  /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
490  worked, hence we need to go through this list and set
491  CLOEXEC everywhere in any case */
492  for (i = 0; i < fds_to_use; i++)
494 
495  break;
496  }
497 
498  if (!found)
499  *n_fds = 0;
500 
501  /* put length back (doesn't actually realloc) */
502  _dbus_string_set_length (buffer, start + bytes_read);
503 
504 #if 0
505  if (bytes_read > 0)
506  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
507 #endif
508 
509  return bytes_read;
510  }
511 #endif
512 }
513 
514 int
515 _dbus_write_socket_with_unix_fds(DBusSocket fd,
516  const DBusString *buffer,
517  int start,
518  int len,
519  const int *fds,
520  int n_fds) {
521 
522 #ifndef HAVE_UNIX_FD_PASSING
523 
524  if (n_fds > 0) {
525  errno = ENOTSUP;
526  return -1;
527  }
528 
529  return _dbus_write_socket(fd, buffer, start, len);
530 #else
531  return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
532 #endif
533 }
534 
535 int
536 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
537  const DBusString *buffer1,
538  int start1,
539  int len1,
540  const DBusString *buffer2,
541  int start2,
542  int len2,
543  const int *fds,
544  int n_fds) {
545 
546 #ifndef HAVE_UNIX_FD_PASSING
547 
548  if (n_fds > 0) {
549  errno = ENOTSUP;
550  return -1;
551  }
552 
553  return _dbus_write_socket_two(fd,
554  buffer1, start1, len1,
555  buffer2, start2, len2);
556 #else
557 
558  struct msghdr m;
559  struct cmsghdr *cm;
560  struct iovec iov[2];
561  int bytes_written;
562 
563  _dbus_assert (len1 >= 0);
564  _dbus_assert (len2 >= 0);
565  _dbus_assert (n_fds >= 0);
566 
567  _DBUS_ZERO(iov);
568  iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
569  iov[0].iov_len = len1;
570 
571  if (buffer2)
572  {
573  iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
574  iov[1].iov_len = len2;
575  }
576 
577  _DBUS_ZERO(m);
578  m.msg_iov = iov;
579  m.msg_iovlen = buffer2 ? 2 : 1;
580 
581  if (n_fds > 0)
582  {
583  m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
584  m.msg_control = alloca(m.msg_controllen);
585  memset(m.msg_control, 0, m.msg_controllen);
586 
587  cm = CMSG_FIRSTHDR(&m);
588  cm->cmsg_level = SOL_SOCKET;
589  cm->cmsg_type = SCM_RIGHTS;
590  cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
591  memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
592  }
593 
594  again:
595 
596  bytes_written = sendmsg (fd.fd, &m, 0
597 #if HAVE_DECL_MSG_NOSIGNAL
598  |MSG_NOSIGNAL
599 #endif
600  );
601 
602  if (bytes_written < 0 && errno == EINTR)
603  goto again;
604 
605 #if 0
606  if (bytes_written > 0)
607  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
608 #endif
609 
610  return bytes_written;
611 #endif
612 }
613 
627 int
629  const DBusString *buffer1,
630  int start1,
631  int len1,
632  const DBusString *buffer2,
633  int start2,
634  int len2)
635 {
636 #if HAVE_DECL_MSG_NOSIGNAL
637  struct iovec vectors[2];
638  const char *data1;
639  const char *data2;
640  int bytes_written;
641  struct msghdr m;
642 
643  _dbus_assert (buffer1 != NULL);
644  _dbus_assert (start1 >= 0);
645  _dbus_assert (start2 >= 0);
646  _dbus_assert (len1 >= 0);
647  _dbus_assert (len2 >= 0);
648 
649  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
650 
651  if (buffer2 != NULL)
652  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
653  else
654  {
655  data2 = NULL;
656  start2 = 0;
657  len2 = 0;
658  }
659 
660  vectors[0].iov_base = (char*) data1;
661  vectors[0].iov_len = len1;
662  vectors[1].iov_base = (char*) data2;
663  vectors[1].iov_len = len2;
664 
665  _DBUS_ZERO(m);
666  m.msg_iov = vectors;
667  m.msg_iovlen = data2 ? 2 : 1;
668 
669  again:
670 
671  bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
672 
673  if (bytes_written < 0 && errno == EINTR)
674  goto again;
675 
676  return bytes_written;
677 
678 #else
679  return _dbus_write_two (fd.fd, buffer1, start1, len1,
680  buffer2, start2, len2);
681 #endif
682 }
683 
700 int
701 _dbus_read (int fd,
702  DBusString *buffer,
703  int count)
704 {
705  int bytes_read;
706  int start;
707  char *data;
708 
709  _dbus_assert (count >= 0);
710 
711  start = _dbus_string_get_length (buffer);
712 
713  if (!_dbus_string_lengthen (buffer, count))
714  {
715  errno = ENOMEM;
716  return -1;
717  }
718 
719  data = _dbus_string_get_data_len (buffer, start, count);
720 
721  again:
722 
723  bytes_read = read (fd, data, count);
724 
725  if (bytes_read < 0)
726  {
727  if (errno == EINTR)
728  goto again;
729  else
730  {
731  /* put length back (note that this doesn't actually realloc anything) */
732  _dbus_string_set_length (buffer, start);
733  return -1;
734  }
735  }
736  else
737  {
738  /* put length back (doesn't actually realloc) */
739  _dbus_string_set_length (buffer, start + bytes_read);
740 
741 #if 0
742  if (bytes_read > 0)
743  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
744 #endif
745 
746  return bytes_read;
747  }
748 }
749 
760 int
761 _dbus_write (int fd,
762  const DBusString *buffer,
763  int start,
764  int len)
765 {
766  const char *data;
767  int bytes_written;
768 
769  data = _dbus_string_get_const_data_len (buffer, start, len);
770 
771  again:
772 
773  bytes_written = write (fd, data, len);
774 
775  if (bytes_written < 0 && errno == EINTR)
776  goto again;
777 
778 #if 0
779  if (bytes_written > 0)
780  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
781 #endif
782 
783  return bytes_written;
784 }
785 
806 int
808  const DBusString *buffer1,
809  int start1,
810  int len1,
811  const DBusString *buffer2,
812  int start2,
813  int len2)
814 {
815  _dbus_assert (buffer1 != NULL);
816  _dbus_assert (start1 >= 0);
817  _dbus_assert (start2 >= 0);
818  _dbus_assert (len1 >= 0);
819  _dbus_assert (len2 >= 0);
820 
821 #ifdef HAVE_WRITEV
822  {
823  struct iovec vectors[2];
824  const char *data1;
825  const char *data2;
826  int bytes_written;
827 
828  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
829 
830  if (buffer2 != NULL)
831  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
832  else
833  {
834  data2 = NULL;
835  start2 = 0;
836  len2 = 0;
837  }
838 
839  vectors[0].iov_base = (char*) data1;
840  vectors[0].iov_len = len1;
841  vectors[1].iov_base = (char*) data2;
842  vectors[1].iov_len = len2;
843 
844  again:
845 
846  bytes_written = writev (fd,
847  vectors,
848  data2 ? 2 : 1);
849 
850  if (bytes_written < 0 && errno == EINTR)
851  goto again;
852 
853  return bytes_written;
854  }
855 #else /* HAVE_WRITEV */
856  {
857  int ret1, ret2;
858 
859  ret1 = _dbus_write (fd, buffer1, start1, len1);
860  if (ret1 == len1 && buffer2 != NULL)
861  {
862  ret2 = _dbus_write (fd, buffer2, start2, len2);
863  if (ret2 < 0)
864  ret2 = 0; /* we can't report an error as the first write was OK */
865 
866  return ret1 + ret2;
867  }
868  else
869  return ret1;
870  }
871 #endif /* !HAVE_WRITEV */
872 }
873 
874 #define _DBUS_MAX_SUN_PATH_LENGTH 99
875 
905 int
906 _dbus_connect_unix_socket (const char *path,
907  dbus_bool_t abstract,
908  DBusError *error)
909 {
910  int fd;
911  size_t path_len;
912  struct sockaddr_un addr;
913  _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
914 
915  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
916 
917  _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
918  path, abstract);
919 
920 
921  if (!_dbus_open_unix_socket (&fd, error))
922  {
923  _DBUS_ASSERT_ERROR_IS_SET(error);
924  return -1;
925  }
926  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
927 
928  _DBUS_ZERO (addr);
929  addr.sun_family = AF_UNIX;
930  path_len = strlen (path);
931 
932  if (abstract)
933  {
934 #ifdef HAVE_ABSTRACT_SOCKETS
935  addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
936  path_len++; /* Account for the extra nul byte added to the start of sun_path */
937 
938  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
939  {
941  "Abstract socket name too long\n");
942  _dbus_close (fd, NULL);
943  return -1;
944  }
945 
946  strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
947  /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
948 #else /* HAVE_ABSTRACT_SOCKETS */
950  "Operating system does not support abstract socket namespace\n");
951  _dbus_close (fd, NULL);
952  return -1;
953 #endif /* ! HAVE_ABSTRACT_SOCKETS */
954  }
955  else
956  {
957  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
958  {
960  "Socket name too long\n");
961  _dbus_close (fd, NULL);
962  return -1;
963  }
964 
965  strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
966  }
967 
968  if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
969  {
970  dbus_set_error (error,
971  _dbus_error_from_errno (errno),
972  "Failed to connect to socket %s: %s",
973  path, _dbus_strerror (errno));
974 
975  _dbus_close (fd, NULL);
976  return -1;
977  }
978 
979  if (!_dbus_set_fd_nonblocking (fd, error))
980  {
981  _DBUS_ASSERT_ERROR_IS_SET (error);
982 
983  _dbus_close (fd, NULL);
984  return -1;
985  }
986 
987  return fd;
988 }
989 
1002 int
1003 _dbus_connect_exec (const char *path,
1004  char *const argv[],
1005  DBusError *error)
1006 {
1007  int fds[2];
1008  pid_t pid;
1009  int retval;
1010  dbus_bool_t cloexec_done = 0;
1011 
1012  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1013 
1014  _dbus_verbose ("connecting to process %s\n", path);
1015 
1016 #ifdef SOCK_CLOEXEC
1017  retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
1018  cloexec_done = (retval >= 0);
1019 
1020  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
1021 #endif
1022  {
1023  retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
1024  }
1025 
1026  if (retval < 0)
1027  {
1028  dbus_set_error (error,
1029  _dbus_error_from_errno (errno),
1030  "Failed to create socket pair: %s",
1031  _dbus_strerror (errno));
1032  return -1;
1033  }
1034 
1035  if (!cloexec_done)
1036  {
1037  _dbus_fd_set_close_on_exec (fds[0]);
1038  _dbus_fd_set_close_on_exec (fds[1]);
1039  }
1040 
1041  pid = fork ();
1042  if (pid < 0)
1043  {
1044  dbus_set_error (error,
1045  _dbus_error_from_errno (errno),
1046  "Failed to fork() to call %s: %s",
1047  path, _dbus_strerror (errno));
1048  close (fds[0]);
1049  close (fds[1]);
1050  return -1;
1051  }
1052 
1053  if (pid == 0)
1054  {
1055  /* child */
1056  close (fds[0]);
1057 
1058  dup2 (fds[1], STDIN_FILENO);
1059  dup2 (fds[1], STDOUT_FILENO);
1060 
1061  if (fds[1] != STDIN_FILENO &&
1062  fds[1] != STDOUT_FILENO)
1063  close (fds[1]);
1064 
1065  /* Inherit STDERR and the controlling terminal from the
1066  parent */
1067 
1068  _dbus_close_all ();
1069 
1070  execvp (path, argv);
1071 
1072  fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1073 
1074  _exit(1);
1075  }
1076 
1077  /* parent */
1078  close (fds[1]);
1079 
1080  if (!_dbus_set_fd_nonblocking (fds[0], error))
1081  {
1082  _DBUS_ASSERT_ERROR_IS_SET (error);
1083 
1084  close (fds[0]);
1085  return -1;
1086  }
1087 
1088  return fds[0];
1089 }
1090 
1108 int
1109 _dbus_listen_unix_socket (const char *path,
1110  dbus_bool_t abstract,
1111  DBusError *error)
1112 {
1113  int listen_fd;
1114  struct sockaddr_un addr;
1115  size_t path_len;
1116  _DBUS_STATIC_ASSERT (sizeof (addr.sun_path) > _DBUS_MAX_SUN_PATH_LENGTH);
1117 
1118  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1119 
1120  _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1121  path, abstract);
1122 
1123  if (!_dbus_open_unix_socket (&listen_fd, error))
1124  {
1125  _DBUS_ASSERT_ERROR_IS_SET(error);
1126  return -1;
1127  }
1128  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1129 
1130  _DBUS_ZERO (addr);
1131  addr.sun_family = AF_UNIX;
1132  path_len = strlen (path);
1133 
1134  if (abstract)
1135  {
1136 #ifdef HAVE_ABSTRACT_SOCKETS
1137  /* remember that abstract names aren't nul-terminated so we rely
1138  * on sun_path being filled in with zeroes above.
1139  */
1140  addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1141  path_len++; /* Account for the extra nul byte added to the start of sun_path */
1142 
1143  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1144  {
1146  "Abstract socket name too long\n");
1147  _dbus_close (listen_fd, NULL);
1148  return -1;
1149  }
1150 
1151  strncpy (&addr.sun_path[1], path, sizeof (addr.sun_path) - 2);
1152  /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1153 #else /* HAVE_ABSTRACT_SOCKETS */
1155  "Operating system does not support abstract socket namespace\n");
1156  _dbus_close (listen_fd, NULL);
1157  return -1;
1158 #endif /* ! HAVE_ABSTRACT_SOCKETS */
1159  }
1160  else
1161  {
1162  /* Discussed security implications of this with Nalin,
1163  * and we couldn't think of where it would kick our ass, but
1164  * it still seems a bit sucky. It also has non-security suckage;
1165  * really we'd prefer to exit if the socket is already in use.
1166  * But there doesn't seem to be a good way to do this.
1167  *
1168  * Just to be extra careful, I threw in the stat() - clearly
1169  * the stat() can't *fix* any security issue, but it at least
1170  * avoids inadvertent/accidental data loss.
1171  */
1172  {
1173  struct stat sb;
1174 
1175  if (stat (path, &sb) == 0 &&
1176  S_ISSOCK (sb.st_mode))
1177  unlink (path);
1178  }
1179 
1180  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1181  {
1183  "Socket name too long\n");
1184  _dbus_close (listen_fd, NULL);
1185  return -1;
1186  }
1187 
1188  strncpy (addr.sun_path, path, sizeof (addr.sun_path) - 1);
1189  }
1190 
1191  if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1192  {
1193  dbus_set_error (error, _dbus_error_from_errno (errno),
1194  "Failed to bind socket \"%s\": %s",
1195  path, _dbus_strerror (errno));
1196  _dbus_close (listen_fd, NULL);
1197  return -1;
1198  }
1199 
1200  if (listen (listen_fd, SOMAXCONN /* backlog */) < 0)
1201  {
1202  dbus_set_error (error, _dbus_error_from_errno (errno),
1203  "Failed to listen on socket \"%s\": %s",
1204  path, _dbus_strerror (errno));
1205  _dbus_close (listen_fd, NULL);
1206  return -1;
1207  }
1208 
1209  if (!_dbus_set_fd_nonblocking (listen_fd, error))
1210  {
1211  _DBUS_ASSERT_ERROR_IS_SET (error);
1212  _dbus_close (listen_fd, NULL);
1213  return -1;
1214  }
1215 
1216  /* Try opening up the permissions, but if we can't, just go ahead
1217  * and continue, maybe it will be good enough.
1218  */
1219  if (!abstract && chmod (path, 0777) < 0)
1220  _dbus_warn ("Could not set mode 0777 on socket %s\n",
1221  path);
1222 
1223  return listen_fd;
1224 }
1225 
1236 int
1238  DBusError *error)
1239 {
1240 #ifdef HAVE_SYSTEMD
1241  int r, n;
1242  int fd;
1243  DBusSocket *new_fds;
1244 
1245  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1246 
1247  n = sd_listen_fds (TRUE);
1248  if (n < 0)
1249  {
1251  "Failed to acquire systemd socket: %s",
1252  _dbus_strerror (-n));
1253  return -1;
1254  }
1255 
1256  if (n <= 0)
1257  {
1259  "No socket received.");
1260  return -1;
1261  }
1262 
1263  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1264  {
1265  r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1266  if (r < 0)
1267  {
1269  "Failed to verify systemd socket type: %s",
1270  _dbus_strerror (-r));
1271  return -1;
1272  }
1273 
1274  if (!r)
1275  {
1277  "Passed socket has wrong type.");
1278  return -1;
1279  }
1280  }
1281 
1282  /* OK, the file descriptors are all good, so let's take posession of
1283  them then. */
1284 
1285  new_fds = dbus_new (DBusSocket, n);
1286  if (!new_fds)
1287  {
1289  "Failed to allocate file handle array.");
1290  goto fail;
1291  }
1292 
1293  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1294  {
1295  if (!_dbus_set_fd_nonblocking (fd, error))
1296  {
1297  _DBUS_ASSERT_ERROR_IS_SET (error);
1298  goto fail;
1299  }
1300 
1301  new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1302  }
1303 
1304  *fds = new_fds;
1305  return n;
1306 
1307  fail:
1308 
1309  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1310  {
1311  _dbus_close (fd, NULL);
1312  }
1313 
1314  dbus_free (new_fds);
1315  return -1;
1316 #else
1318  "dbus was compiled without systemd support");
1319  return -1;
1320 #endif
1321 }
1322 
1336 DBusSocket
1337 _dbus_connect_tcp_socket (const char *host,
1338  const char *port,
1339  const char *family,
1340  DBusError *error)
1341 {
1342  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1343 }
1344 
1345 DBusSocket
1346 _dbus_connect_tcp_socket_with_nonce (const char *host,
1347  const char *port,
1348  const char *family,
1349  const char *noncefile,
1350  DBusError *error)
1351 {
1352  int saved_errno = 0;
1353  DBusSocket fd = DBUS_SOCKET_INIT;
1354  int res;
1355  struct addrinfo hints;
1356  struct addrinfo *ai, *tmp;
1357 
1358  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1359 
1360  _DBUS_ZERO (hints);
1361 
1362  if (!family)
1363  hints.ai_family = AF_UNSPEC;
1364  else if (!strcmp(family, "ipv4"))
1365  hints.ai_family = AF_INET;
1366  else if (!strcmp(family, "ipv6"))
1367  hints.ai_family = AF_INET6;
1368  else
1369  {
1370  dbus_set_error (error,
1372  "Unknown address family %s", family);
1373  return _dbus_socket_get_invalid ();
1374  }
1375  hints.ai_protocol = IPPROTO_TCP;
1376  hints.ai_socktype = SOCK_STREAM;
1377  hints.ai_flags = AI_ADDRCONFIG;
1378 
1379  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1380  {
1381  dbus_set_error (error,
1382  _dbus_error_from_errno (errno),
1383  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1384  host, port, gai_strerror(res), res);
1385  return _dbus_socket_get_invalid ();
1386  }
1387 
1388  tmp = ai;
1389  while (tmp)
1390  {
1391  if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1392  {
1393  freeaddrinfo(ai);
1394  _DBUS_ASSERT_ERROR_IS_SET(error);
1395  return _dbus_socket_get_invalid ();
1396  }
1397  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1398 
1399  if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1400  {
1401  saved_errno = errno;
1402  _dbus_close (fd.fd, NULL);
1403  fd.fd = -1;
1404  tmp = tmp->ai_next;
1405  continue;
1406  }
1407 
1408  break;
1409  }
1410  freeaddrinfo(ai);
1411 
1412  if (fd.fd == -1)
1413  {
1414  dbus_set_error (error,
1415  _dbus_error_from_errno (saved_errno),
1416  "Failed to connect to socket \"%s:%s\" %s",
1417  host, port, _dbus_strerror(saved_errno));
1418  return _dbus_socket_get_invalid ();
1419  }
1420 
1421  if (noncefile != NULL)
1422  {
1423  DBusString noncefileStr;
1424  dbus_bool_t ret;
1425  _dbus_string_init_const (&noncefileStr, noncefile);
1426  ret = _dbus_send_nonce (fd, &noncefileStr, error);
1427  _dbus_string_free (&noncefileStr);
1428 
1429  if (!ret)
1430  {
1431  _dbus_close (fd.fd, NULL);
1432  return _dbus_socket_get_invalid ();
1433  }
1434  }
1435 
1436  if (!_dbus_set_fd_nonblocking (fd.fd, error))
1437  {
1438  _dbus_close (fd.fd, NULL);
1439  return _dbus_socket_get_invalid ();
1440  }
1441 
1442  return fd;
1443 }
1444 
1461 int
1462 _dbus_listen_tcp_socket (const char *host,
1463  const char *port,
1464  const char *family,
1465  DBusString *retport,
1466  DBusSocket **fds_p,
1467  DBusError *error)
1468 {
1469  int saved_errno;
1470  int nlisten_fd = 0, res, i;
1471  DBusSocket *listen_fd = NULL;
1472  struct addrinfo hints;
1473  struct addrinfo *ai, *tmp;
1474  unsigned int reuseaddr;
1475 
1476  *fds_p = NULL;
1477  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1478 
1479  _DBUS_ZERO (hints);
1480 
1481  if (!family)
1482  hints.ai_family = AF_UNSPEC;
1483  else if (!strcmp(family, "ipv4"))
1484  hints.ai_family = AF_INET;
1485  else if (!strcmp(family, "ipv6"))
1486  hints.ai_family = AF_INET6;
1487  else
1488  {
1489  dbus_set_error (error,
1491  "Unknown address family %s", family);
1492  return -1;
1493  }
1494 
1495  hints.ai_protocol = IPPROTO_TCP;
1496  hints.ai_socktype = SOCK_STREAM;
1497  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1498 
1499  redo_lookup_with_port:
1500  ai = NULL;
1501  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1502  {
1503  dbus_set_error (error,
1504  _dbus_error_from_errno (errno),
1505  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1506  host ? host : "*", port, gai_strerror(res), res);
1507  goto failed;
1508  }
1509 
1510  tmp = ai;
1511  while (tmp)
1512  {
1513  int fd = -1, tcp_nodelay_on;
1514  DBusSocket *newlisten_fd;
1515 
1516  if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1517  {
1518  _DBUS_ASSERT_ERROR_IS_SET(error);
1519  goto failed;
1520  }
1521  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1522 
1523  reuseaddr = 1;
1524  if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1525  {
1526  _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1527  host ? host : "*", port, _dbus_strerror (errno));
1528  }
1529 
1530  /* Nagle's algorithm imposes a huge delay on the initial messages
1531  going over TCP. */
1532  tcp_nodelay_on = 1;
1533  if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1534  {
1535  _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1536  host ? host : "*", port, _dbus_strerror (errno));
1537  }
1538 
1539  if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1540  {
1541  saved_errno = errno;
1542  _dbus_close(fd, NULL);
1543  if (saved_errno == EADDRINUSE)
1544  {
1545  /* Depending on kernel policy, binding to an IPv6 address
1546  might implicitly bind to a corresponding IPv4
1547  address or vice versa, resulting in EADDRINUSE for the
1548  other one (e.g. bindv6only=0 on Linux).
1549 
1550  Also, after we "goto redo_lookup_with_port" after binding
1551  a port on one of the possible addresses, we will
1552  try to bind that same port on every address, including the
1553  same address again for a second time; that one will
1554  also fail with EADDRINUSE.
1555 
1556  For both those reasons, ignore EADDRINUSE here */
1557  tmp = tmp->ai_next;
1558  continue;
1559  }
1560  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1561  "Failed to bind socket \"%s:%s\": %s",
1562  host ? host : "*", port, _dbus_strerror (saved_errno));
1563  goto failed;
1564  }
1565 
1566  if (listen (fd, 30 /* backlog */) < 0)
1567  {
1568  saved_errno = errno;
1569  _dbus_close (fd, NULL);
1570  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1571  "Failed to listen on socket \"%s:%s\": %s",
1572  host ? host : "*", port, _dbus_strerror (saved_errno));
1573  goto failed;
1574  }
1575 
1576  newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1577  if (!newlisten_fd)
1578  {
1579  saved_errno = errno;
1580  _dbus_close (fd, NULL);
1581  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1582  "Failed to allocate file handle array: %s",
1583  _dbus_strerror (saved_errno));
1584  goto failed;
1585  }
1586  listen_fd = newlisten_fd;
1587  listen_fd[nlisten_fd].fd = fd;
1588  nlisten_fd++;
1589 
1590  if (!_dbus_string_get_length(retport))
1591  {
1592  /* If the user didn't specify a port, or used 0, then
1593  the kernel chooses a port. After the first address
1594  is bound to, we need to force all remaining addresses
1595  to use the same port */
1596  if (!port || !strcmp(port, "0"))
1597  {
1598  int result;
1599  struct sockaddr_storage addr;
1600  socklen_t addrlen;
1601  char portbuf[50];
1602 
1603  addrlen = sizeof(addr);
1604  result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1605 
1606  if (result == -1 ||
1607  (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1608  portbuf, sizeof(portbuf),
1609  NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1610  {
1611  dbus_set_error (error, _dbus_error_from_errno (errno),
1612  "Failed to resolve port \"%s:%s\": %s (%s)",
1613  host ? host : "*", port, gai_strerror(res), res);
1614  goto failed;
1615  }
1616  if (!_dbus_string_append(retport, portbuf))
1617  {
1619  goto failed;
1620  }
1621 
1622  /* Release current address list & redo lookup */
1623  port = _dbus_string_get_const_data(retport);
1624  freeaddrinfo(ai);
1625  goto redo_lookup_with_port;
1626  }
1627  else
1628  {
1629  if (!_dbus_string_append(retport, port))
1630  {
1632  goto failed;
1633  }
1634  }
1635  }
1636 
1637  tmp = tmp->ai_next;
1638  }
1639  freeaddrinfo(ai);
1640  ai = NULL;
1641 
1642  if (!nlisten_fd)
1643  {
1644  errno = EADDRINUSE;
1645  dbus_set_error (error, _dbus_error_from_errno (errno),
1646  "Failed to bind socket \"%s:%s\": %s",
1647  host ? host : "*", port, _dbus_strerror (errno));
1648  goto failed;
1649  }
1650 
1651  for (i = 0 ; i < nlisten_fd ; i++)
1652  {
1653  if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1654  {
1655  goto failed;
1656  }
1657  }
1658 
1659  *fds_p = listen_fd;
1660 
1661  return nlisten_fd;
1662 
1663  failed:
1664  if (ai)
1665  freeaddrinfo(ai);
1666  for (i = 0 ; i < nlisten_fd ; i++)
1667  _dbus_close(listen_fd[i].fd, NULL);
1668  dbus_free(listen_fd);
1669  return -1;
1670 }
1671 
1672 static dbus_bool_t
1673 write_credentials_byte (int server_fd,
1674  DBusError *error)
1675 {
1676  int bytes_written;
1677  char buf[1] = { '\0' };
1678 #if defined(HAVE_CMSGCRED)
1679  union {
1680  struct cmsghdr hdr;
1681  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1682  } cmsg;
1683  struct iovec iov;
1684  struct msghdr msg;
1685  iov.iov_base = buf;
1686  iov.iov_len = 1;
1687 
1688  _DBUS_ZERO(msg);
1689  msg.msg_iov = &iov;
1690  msg.msg_iovlen = 1;
1691 
1692  msg.msg_control = (caddr_t) &cmsg;
1693  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1694  _DBUS_ZERO(cmsg);
1695  cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1696  cmsg.hdr.cmsg_level = SOL_SOCKET;
1697  cmsg.hdr.cmsg_type = SCM_CREDS;
1698 #endif
1699 
1700  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1701 
1702  again:
1703 
1704 #if defined(HAVE_CMSGCRED)
1705  bytes_written = sendmsg (server_fd, &msg, 0
1706 #if HAVE_DECL_MSG_NOSIGNAL
1707  |MSG_NOSIGNAL
1708 #endif
1709  );
1710 
1711  /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1712  * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1713  * only allows that on AF_UNIX. Try just doing a send() instead. */
1714  if (bytes_written < 0 && errno == EINVAL)
1715 #endif
1716  {
1717  bytes_written = send (server_fd, buf, 1, 0
1718 #if HAVE_DECL_MSG_NOSIGNAL
1719  |MSG_NOSIGNAL
1720 #endif
1721  );
1722  }
1723 
1724  if (bytes_written < 0 && errno == EINTR)
1725  goto again;
1726 
1727  if (bytes_written < 0)
1728  {
1729  dbus_set_error (error, _dbus_error_from_errno (errno),
1730  "Failed to write credentials byte: %s",
1731  _dbus_strerror (errno));
1732  return FALSE;
1733  }
1734  else if (bytes_written == 0)
1735  {
1737  "wrote zero bytes writing credentials byte");
1738  return FALSE;
1739  }
1740  else
1741  {
1742  _dbus_assert (bytes_written == 1);
1743  _dbus_verbose ("wrote credentials byte\n");
1744  return TRUE;
1745  }
1746 }
1747 
1748 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1749 static dbus_bool_t
1750 add_linux_security_label_to_credentials (int client_fd,
1751  DBusCredentials *credentials)
1752 {
1753 #if defined(__linux__) && defined(SO_PEERSEC)
1754  DBusString buf;
1755  socklen_t len = 1024;
1756  dbus_bool_t oom = FALSE;
1757 
1758  if (!_dbus_string_init_preallocated (&buf, len) ||
1759  !_dbus_string_set_length (&buf, len))
1760  return FALSE;
1761 
1762  while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1763  _dbus_string_get_data (&buf), &len) < 0)
1764  {
1765  int e = errno;
1766 
1767  _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1768  _dbus_strerror (e), (unsigned long) len);
1769 
1770  if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1771  {
1772  _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1773  _dbus_strerror (e));
1774  goto out;
1775  }
1776 
1777  /* If not enough space, len is updated to be enough.
1778  * Try again with a large enough buffer. */
1779  if (!_dbus_string_set_length (&buf, len))
1780  {
1781  oom = TRUE;
1782  goto out;
1783  }
1784 
1785  _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1786  }
1787 
1788  if (len <= 0)
1789  {
1790  _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1791  (unsigned long) len);
1792  goto out;
1793  }
1794 
1795  if (len > _dbus_string_get_length_uint (&buf))
1796  {
1797  _dbus_verbose ("%lu > %u", (unsigned long) len,
1798  _dbus_string_get_length_uint (&buf));
1799  _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1800  }
1801 
1802  if (_dbus_string_get_byte (&buf, len - 1) == 0)
1803  {
1804  /* the kernel included the trailing \0 in its count,
1805  * but DBusString always has an extra \0 after the data anyway */
1806  _dbus_verbose ("subtracting trailing \\0\n");
1807  len--;
1808  }
1809 
1810  if (!_dbus_string_set_length (&buf, len))
1811  {
1812  _dbus_assert_not_reached ("shortening string should not lead to OOM");
1813  oom = TRUE;
1814  goto out;
1815  }
1816 
1817  if (strlen (_dbus_string_get_const_data (&buf)) != len)
1818  {
1819  /* LSM people on the linux-security-module@ mailing list say this
1820  * should never happen: the label should be a bytestring with
1821  * an optional trailing \0 */
1822  _dbus_verbose ("security label from kernel had an embedded \\0, "
1823  "ignoring it\n");
1824  goto out;
1825  }
1826 
1827  _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1828  (unsigned long) len,
1829  _dbus_string_get_const_data (&buf));
1830 
1832  _dbus_string_get_const_data (&buf)))
1833  {
1834  oom = TRUE;
1835  goto out;
1836  }
1837 
1838 out:
1839  _dbus_string_free (&buf);
1840  return !oom;
1841 #else
1842  /* no error */
1843  return TRUE;
1844 #endif
1845 }
1846 
1889  DBusCredentials *credentials,
1890  DBusError *error)
1891 {
1892  struct msghdr msg;
1893  struct iovec iov;
1894  char buf;
1895  dbus_uid_t uid_read;
1896  dbus_pid_t pid_read;
1897  int bytes_read;
1898 
1899 #ifdef HAVE_CMSGCRED
1900  union {
1901  struct cmsghdr hdr;
1902  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1903  } cmsg;
1904 #endif
1905 
1906  /* The POSIX spec certainly doesn't promise this, but
1907  * we need these assertions to fail as soon as we're wrong about
1908  * it so we can do the porting fixups
1909  */
1910  _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1911  _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1912  _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1913 
1914  uid_read = DBUS_UID_UNSET;
1915  pid_read = DBUS_PID_UNSET;
1916 
1917  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1918 
1919  _dbus_credentials_clear (credentials);
1920 
1921  iov.iov_base = &buf;
1922  iov.iov_len = 1;
1923 
1924  _DBUS_ZERO(msg);
1925  msg.msg_iov = &iov;
1926  msg.msg_iovlen = 1;
1927 
1928 #if defined(HAVE_CMSGCRED)
1929  _DBUS_ZERO(cmsg);
1930  msg.msg_control = (caddr_t) &cmsg;
1931  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1932 #endif
1933 
1934  again:
1935  bytes_read = recvmsg (client_fd.fd, &msg, 0);
1936 
1937  if (bytes_read < 0)
1938  {
1939  if (errno == EINTR)
1940  goto again;
1941 
1942  /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1943  * normally only call read_credentials if the socket was ready
1944  * for reading
1945  */
1946 
1947  dbus_set_error (error, _dbus_error_from_errno (errno),
1948  "Failed to read credentials byte: %s",
1949  _dbus_strerror (errno));
1950  return FALSE;
1951  }
1952  else if (bytes_read == 0)
1953  {
1954  /* this should not happen unless we are using recvmsg wrong,
1955  * so is essentially here for paranoia
1956  */
1958  "Failed to read credentials byte (zero-length read)");
1959  return FALSE;
1960  }
1961  else if (buf != '\0')
1962  {
1964  "Credentials byte was not nul");
1965  return FALSE;
1966  }
1967 
1968  _dbus_verbose ("read credentials byte\n");
1969 
1970  {
1971 #ifdef SO_PEERCRED
1972  /* Supported by at least Linux and OpenBSD, with minor differences.
1973  *
1974  * This mechanism passes the process ID through and does not require
1975  * the peer's cooperation, so we prefer it over all others. Notably,
1976  * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
1977  * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
1978  * because this is much less fragile.
1979  */
1980 #ifdef __OpenBSD__
1981  struct sockpeercred cr;
1982 #else
1983  struct ucred cr;
1984 #endif
1985  int cr_len = sizeof (cr);
1986 
1987  if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
1988  {
1989  _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
1990  _dbus_strerror (errno));
1991  }
1992  else if (cr_len != sizeof (cr))
1993  {
1994  _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
1995  cr_len, (int) sizeof (cr));
1996  }
1997  else
1998  {
1999  pid_read = cr.pid;
2000  uid_read = cr.uid;
2001  }
2002 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
2003  /* Another variant of the above - used on NetBSD
2004  */
2005  struct unpcbid cr;
2006  socklen_t cr_len = sizeof (cr);
2007 
2008  if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
2009  {
2010  _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
2011  _dbus_strerror (errno));
2012  }
2013  else if (cr_len != sizeof (cr))
2014  {
2015  _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
2016  cr_len, (int) sizeof (cr));
2017  }
2018  else
2019  {
2020  pid_read = cr.unp_pid;
2021  uid_read = cr.unp_euid;
2022  }
2023 #elif defined(HAVE_CMSGCRED)
2024  /* We only check for HAVE_CMSGCRED, but we're really assuming that the
2025  * presence of that struct implies SCM_CREDS. Supported by at least
2026  * FreeBSD and DragonflyBSD.
2027  *
2028  * This mechanism requires the peer to help us (it has to send us a
2029  * SCM_CREDS message) but it does pass the process ID through,
2030  * which makes it better than getpeereid().
2031  */
2032  struct cmsgcred *cred;
2033  struct cmsghdr *cmsgp;
2034 
2035  for (cmsgp = CMSG_FIRSTHDR (&msg);
2036  cmsgp != NULL;
2037  cmsgp = CMSG_NXTHDR (&msg, cmsgp))
2038  {
2039  if (cmsgp->cmsg_type == SCM_CREDS &&
2040  cmsgp->cmsg_level == SOL_SOCKET &&
2041  cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
2042  {
2043  cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
2044  pid_read = cred->cmcred_pid;
2045  uid_read = cred->cmcred_euid;
2046  break;
2047  }
2048  }
2049 
2050 #elif defined(HAVE_GETPEERUCRED)
2051  /* Supported in at least Solaris >= 10. It should probably be higher
2052  * up this list, because it carries the pid and we use this code path
2053  * for audit data. */
2054  ucred_t * ucred = NULL;
2055  if (getpeerucred (client_fd.fd, &ucred) == 0)
2056  {
2057 #ifdef HAVE_ADT
2058  adt_session_data_t *adth = NULL;
2059 #endif
2060  pid_read = ucred_getpid (ucred);
2061  uid_read = ucred_geteuid (ucred);
2062 #ifdef HAVE_ADT
2063  /* generate audit session data based on socket ucred */
2064  if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
2065  {
2066  _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
2067  }
2068  else
2069  {
2070  if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2071  {
2072  _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2073  }
2074  else
2075  {
2076  adt_export_data_t *data = NULL;
2077  size_t size = adt_export_session_data (adth, &data);
2078  if (size <= 0)
2079  {
2080  _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2081  }
2082  else
2083  {
2084  _dbus_credentials_add_adt_audit_data (credentials, data, size);
2085  free (data);
2086  }
2087  }
2088  (void) adt_end_session (adth);
2089  }
2090 #endif /* HAVE_ADT */
2091  }
2092  else
2093  {
2094  _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2095  }
2096  if (ucred != NULL)
2097  ucred_free (ucred);
2098 
2099  /* ----------------------------------------------------------------
2100  * When adding new mechanisms, please add them above this point
2101  * if they support passing the process ID through, or below if not.
2102  * ---------------------------------------------------------------- */
2103 
2104 #elif defined(HAVE_GETPEEREID)
2105  /* getpeereid() originates from D.J. Bernstein and is fairly
2106  * widely-supported. According to a web search, it might be present in
2107  * any/all of:
2108  *
2109  * - AIX?
2110  * - Blackberry?
2111  * - Cygwin
2112  * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2113  * - Mac OS X
2114  * - Minix 3.1.8+
2115  * - MirBSD?
2116  * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2117  * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2118  * - QNX?
2119  */
2120  uid_t euid;
2121  gid_t egid;
2122  if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2123  {
2124  uid_read = euid;
2125  }
2126  else
2127  {
2128  _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2129  }
2130 #else /* no supported mechanism */
2131 
2132 #warning Socket credentials not supported on this Unix OS
2133 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2134 
2135  /* Please add other operating systems known to support at least one of
2136  * the mechanisms above to this list, keeping alphabetical order.
2137  * Everything not in this list is best-effort.
2138  */
2139 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2140  defined(__linux__) || \
2141  defined(__OpenBSD__) || \
2142  defined(__NetBSD__)
2143 # error Credentials passing not working on this OS is a regression!
2144 #endif
2145 
2146  _dbus_verbose ("Socket credentials not supported on this OS\n");
2147 #endif
2148  }
2149 
2150  _dbus_verbose ("Credentials:"
2151  " pid "DBUS_PID_FORMAT
2152  " uid "DBUS_UID_FORMAT
2153  "\n",
2154  pid_read,
2155  uid_read);
2156 
2157  if (pid_read != DBUS_PID_UNSET)
2158  {
2159  if (!_dbus_credentials_add_pid (credentials, pid_read))
2160  {
2161  _DBUS_SET_OOM (error);
2162  return FALSE;
2163  }
2164  }
2165 
2166  if (uid_read != DBUS_UID_UNSET)
2167  {
2168  if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2169  {
2170  _DBUS_SET_OOM (error);
2171  return FALSE;
2172  }
2173  }
2174 
2175  if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2176  {
2177  _DBUS_SET_OOM (error);
2178  return FALSE;
2179  }
2180 
2181  return TRUE;
2182 }
2183 
2203  DBusError *error)
2204 {
2205  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2206 
2207  if (write_credentials_byte (server_fd.fd, error))
2208  return TRUE;
2209  else
2210  return FALSE;
2211 }
2212 
2222 DBusSocket
2224 {
2225  DBusSocket client_fd;
2226  struct sockaddr addr;
2227  socklen_t addrlen;
2228 #ifdef HAVE_ACCEPT4
2229  dbus_bool_t cloexec_done;
2230 #endif
2231 
2232  addrlen = sizeof (addr);
2233 
2234  retry:
2235 
2236 #ifdef HAVE_ACCEPT4
2237  /*
2238  * At compile-time, we assume that if accept4() is available in
2239  * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2240  * not necessarily true that either is supported by the running kernel.
2241  */
2242  client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2243  cloexec_done = client_fd.fd >= 0;
2244 
2245  if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2246 #endif
2247  {
2248  client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2249  }
2250 
2251  if (client_fd.fd < 0)
2252  {
2253  if (errno == EINTR)
2254  goto retry;
2255  }
2256 
2257  _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2258 
2259 #ifdef HAVE_ACCEPT4
2260  if (!cloexec_done)
2261 #endif
2262  {
2263  _dbus_fd_set_close_on_exec(client_fd.fd);
2264  }
2265 
2266  return client_fd;
2267 }
2268 
2279 {
2280  const char *directory;
2281  struct stat sb;
2282 
2283  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2284 
2285  directory = _dbus_string_get_const_data (dir);
2286 
2287  if (stat (directory, &sb) < 0)
2288  {
2289  dbus_set_error (error, _dbus_error_from_errno (errno),
2290  "%s", _dbus_strerror (errno));
2291 
2292  return FALSE;
2293  }
2294 
2295  if (sb.st_uid != geteuid ())
2296  {
2298  "%s directory is owned by user %lu, not %lu",
2299  directory,
2300  (unsigned long) sb.st_uid,
2301  (unsigned long) geteuid ());
2302  return FALSE;
2303  }
2304 
2305  if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2306  (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2307  {
2309  "%s directory is not private to the user", directory);
2310  return FALSE;
2311  }
2312 
2313  return TRUE;
2314 }
2315 
2316 static dbus_bool_t
2317 fill_user_info_from_passwd (struct passwd *p,
2318  DBusUserInfo *info,
2319  DBusError *error)
2320 {
2321  _dbus_assert (p->pw_name != NULL);
2322  _dbus_assert (p->pw_dir != NULL);
2323 
2324  info->uid = p->pw_uid;
2325  info->primary_gid = p->pw_gid;
2326  info->username = _dbus_strdup (p->pw_name);
2327  info->homedir = _dbus_strdup (p->pw_dir);
2328 
2329  if (info->username == NULL ||
2330  info->homedir == NULL)
2331  {
2333  return FALSE;
2334  }
2335 
2336  return TRUE;
2337 }
2338 
2339 static dbus_bool_t
2340 fill_user_info (DBusUserInfo *info,
2341  dbus_uid_t uid,
2342  const DBusString *username,
2343  DBusError *error)
2344 {
2345  const char *username_c;
2346 
2347  /* exactly one of username/uid provided */
2348  _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2349  _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2350 
2351  info->uid = DBUS_UID_UNSET;
2352  info->primary_gid = DBUS_GID_UNSET;
2353  info->group_ids = NULL;
2354  info->n_group_ids = 0;
2355  info->username = NULL;
2356  info->homedir = NULL;
2357 
2358  if (username != NULL)
2359  username_c = _dbus_string_get_const_data (username);
2360  else
2361  username_c = NULL;
2362 
2363  /* For now assuming that the getpwnam() and getpwuid() flavors
2364  * are always symmetrical, if not we have to add more configure
2365  * checks
2366  */
2367 
2368 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2369  {
2370  struct passwd *p;
2371  int result;
2372  size_t buflen;
2373  char *buf;
2374  struct passwd p_str;
2375 
2376  /* retrieve maximum needed size for buf */
2377  buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2378 
2379  /* sysconf actually returns a long, but everything else expects size_t,
2380  * so just recast here.
2381  * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2382  */
2383  if ((long) buflen <= 0)
2384  buflen = 1024;
2385 
2386  result = -1;
2387  while (1)
2388  {
2389  buf = dbus_malloc (buflen);
2390  if (buf == NULL)
2391  {
2393  return FALSE;
2394  }
2395 
2396  p = NULL;
2397 #ifdef HAVE_POSIX_GETPWNAM_R
2398  if (uid != DBUS_UID_UNSET)
2399  result = getpwuid_r (uid, &p_str, buf, buflen,
2400  &p);
2401  else
2402  result = getpwnam_r (username_c, &p_str, buf, buflen,
2403  &p);
2404 #else
2405  if (uid != DBUS_UID_UNSET)
2406  p = getpwuid_r (uid, &p_str, buf, buflen);
2407  else
2408  p = getpwnam_r (username_c, &p_str, buf, buflen);
2409  result = 0;
2410 #endif /* !HAVE_POSIX_GETPWNAM_R */
2411  //Try a bigger buffer if ERANGE was returned
2412  if (result == ERANGE && buflen < 512 * 1024)
2413  {
2414  dbus_free (buf);
2415  buflen *= 2;
2416  }
2417  else
2418  {
2419  break;
2420  }
2421  }
2422  if (result == 0 && p == &p_str)
2423  {
2424  if (!fill_user_info_from_passwd (p, info, error))
2425  {
2426  dbus_free (buf);
2427  return FALSE;
2428  }
2429  dbus_free (buf);
2430  }
2431  else
2432  {
2433  dbus_set_error (error, _dbus_error_from_errno (errno),
2434  "User \"%s\" unknown or no memory to allocate password entry\n",
2435  username_c ? username_c : "???");
2436  _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2437  dbus_free (buf);
2438  return FALSE;
2439  }
2440  }
2441 #else /* ! HAVE_GETPWNAM_R */
2442  {
2443  /* I guess we're screwed on thread safety here */
2444  struct passwd *p;
2445 
2446  if (uid != DBUS_UID_UNSET)
2447  p = getpwuid (uid);
2448  else
2449  p = getpwnam (username_c);
2450 
2451  if (p != NULL)
2452  {
2453  if (!fill_user_info_from_passwd (p, info, error))
2454  {
2455  return FALSE;
2456  }
2457  }
2458  else
2459  {
2460  dbus_set_error (error, _dbus_error_from_errno (errno),
2461  "User \"%s\" unknown or no memory to allocate password entry\n",
2462  username_c ? username_c : "???");
2463  _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2464  return FALSE;
2465  }
2466  }
2467 #endif /* ! HAVE_GETPWNAM_R */
2468 
2469  /* Fill this in so we can use it to get groups */
2470  username_c = info->username;
2471 
2472 #ifdef HAVE_GETGROUPLIST
2473  {
2474  gid_t *buf;
2475  int buf_count;
2476  int i;
2477  int initial_buf_count;
2478 
2479  initial_buf_count = 17;
2480  buf_count = initial_buf_count;
2481  buf = dbus_new (gid_t, buf_count);
2482  if (buf == NULL)
2483  {
2485  goto failed;
2486  }
2487 
2488  if (getgrouplist (username_c,
2489  info->primary_gid,
2490  buf, &buf_count) < 0)
2491  {
2492  gid_t *new;
2493  /* Presumed cause of negative return code: buf has insufficient
2494  entries to hold the entire group list. The Linux behavior in this
2495  case is to pass back the actual number of groups in buf_count, but
2496  on Mac OS X 10.5, buf_count is unhelpfully left alone.
2497  So as a hack, try to help out a bit by guessing a larger
2498  number of groups, within reason.. might still fail, of course,
2499  but we can at least print a more informative message. I looked up
2500  the "right way" to do this by downloading Apple's own source code
2501  for the "id" command, and it turns out that they use an
2502  undocumented library function getgrouplist_2 (!) which is not
2503  declared in any header in /usr/include (!!). That did not seem
2504  like the way to go here.
2505  */
2506  if (buf_count == initial_buf_count)
2507  {
2508  buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2509  }
2510  new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2511  if (new == NULL)
2512  {
2514  dbus_free (buf);
2515  goto failed;
2516  }
2517 
2518  buf = new;
2519 
2520  errno = 0;
2521  if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2522  {
2523  if (errno == 0)
2524  {
2525  _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2526  username_c, buf_count, buf_count);
2527  }
2528  else
2529  {
2530  dbus_set_error (error,
2531  _dbus_error_from_errno (errno),
2532  "Failed to get groups for username \"%s\" primary GID "
2533  DBUS_GID_FORMAT ": %s\n",
2534  username_c, info->primary_gid,
2535  _dbus_strerror (errno));
2536  dbus_free (buf);
2537  goto failed;
2538  }
2539  }
2540  }
2541 
2542  info->group_ids = dbus_new (dbus_gid_t, buf_count);
2543  if (info->group_ids == NULL)
2544  {
2546  dbus_free (buf);
2547  goto failed;
2548  }
2549 
2550  for (i = 0; i < buf_count; ++i)
2551  info->group_ids[i] = buf[i];
2552 
2553  info->n_group_ids = buf_count;
2554 
2555  dbus_free (buf);
2556  }
2557 #else /* HAVE_GETGROUPLIST */
2558  {
2559  /* We just get the one group ID */
2560  info->group_ids = dbus_new (dbus_gid_t, 1);
2561  if (info->group_ids == NULL)
2562  {
2564  goto failed;
2565  }
2566 
2567  info->n_group_ids = 1;
2568 
2569  (info->group_ids)[0] = info->primary_gid;
2570  }
2571 #endif /* HAVE_GETGROUPLIST */
2572 
2573  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2574 
2575  return TRUE;
2576 
2577  failed:
2578  _DBUS_ASSERT_ERROR_IS_SET (error);
2579  return FALSE;
2580 }
2581 
2592  const DBusString *username,
2593  DBusError *error)
2594 {
2595  return fill_user_info (info, DBUS_UID_UNSET,
2596  username, error);
2597 }
2598 
2609  dbus_uid_t uid,
2610  DBusError *error)
2611 {
2612  return fill_user_info (info, uid,
2613  NULL, error);
2614 }
2615 
2625 {
2626  /* The POSIX spec certainly doesn't promise this, but
2627  * we need these assertions to fail as soon as we're wrong about
2628  * it so we can do the porting fixups
2629  */
2630  _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2631  _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2632  _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2633 
2634  if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2635  return FALSE;
2636  if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2637  return FALSE;
2638 
2639  return TRUE;
2640 }
2641 
2655 {
2656  return _dbus_string_append_uint (str,
2657  _dbus_geteuid ());
2658 }
2659 
2664 dbus_pid_t
2666 {
2667  return getpid ();
2668 }
2669 
2673 dbus_uid_t
2675 {
2676  return getuid ();
2677 }
2678 
2682 dbus_uid_t
2684 {
2685  return geteuid ();
2686 }
2687 
2694 unsigned long
2696 {
2697  return getpid ();
2698 }
2699 
2708 _dbus_parse_uid (const DBusString *uid_str,
2709  dbus_uid_t *uid)
2710 {
2711  int end;
2712  long val;
2713 
2714  if (_dbus_string_get_length (uid_str) == 0)
2715  {
2716  _dbus_verbose ("UID string was zero length\n");
2717  return FALSE;
2718  }
2719 
2720  val = -1;
2721  end = 0;
2722  if (!_dbus_string_parse_int (uid_str, 0, &val,
2723  &end))
2724  {
2725  _dbus_verbose ("could not parse string as a UID\n");
2726  return FALSE;
2727  }
2728 
2729  if (end != _dbus_string_get_length (uid_str))
2730  {
2731  _dbus_verbose ("string contained trailing stuff after UID\n");
2732  return FALSE;
2733  }
2734 
2735  *uid = val;
2736 
2737  return TRUE;
2738 }
2739 
2740 #if !DBUS_USE_SYNC
2741 /* To be thread-safe by default on platforms that don't necessarily have
2742  * atomic operations (notably Debian armel, which is armv4t), we must
2743  * use a mutex that can be initialized statically, like this.
2744  * GLib >= 2.32 uses a similar system.
2745  */
2746 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2747 #endif
2748 
2755 dbus_int32_t
2757 {
2758 #if DBUS_USE_SYNC
2759  return __sync_add_and_fetch(&atomic->value, 1)-1;
2760 #else
2761  dbus_int32_t res;
2762 
2763  pthread_mutex_lock (&atomic_mutex);
2764  res = atomic->value;
2765  atomic->value += 1;
2766  pthread_mutex_unlock (&atomic_mutex);
2767 
2768  return res;
2769 #endif
2770 }
2771 
2778 dbus_int32_t
2780 {
2781 #if DBUS_USE_SYNC
2782  return __sync_sub_and_fetch(&atomic->value, 1)+1;
2783 #else
2784  dbus_int32_t res;
2785 
2786  pthread_mutex_lock (&atomic_mutex);
2787  res = atomic->value;
2788  atomic->value -= 1;
2789  pthread_mutex_unlock (&atomic_mutex);
2790 
2791  return res;
2792 #endif
2793 }
2794 
2802 dbus_int32_t
2804 {
2805 #if DBUS_USE_SYNC
2806  __sync_synchronize ();
2807  return atomic->value;
2808 #else
2809  dbus_int32_t res;
2810 
2811  pthread_mutex_lock (&atomic_mutex);
2812  res = atomic->value;
2813  pthread_mutex_unlock (&atomic_mutex);
2814 
2815  return res;
2816 #endif
2817 }
2818 
2827 int
2829  int n_fds,
2830  int timeout_milliseconds)
2831 {
2832 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2833  /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2834  if (timeout_milliseconds < -1)
2835  {
2836  timeout_milliseconds = -1;
2837  }
2838 
2839  return poll (fds,
2840  n_fds,
2841  timeout_milliseconds);
2842 #else /* ! HAVE_POLL */
2843  /* Emulate poll() in terms of select() */
2844  fd_set read_set, write_set, err_set;
2845  int max_fd = 0;
2846  int i;
2847  struct timeval tv;
2848  int ready;
2849 
2850  FD_ZERO (&read_set);
2851  FD_ZERO (&write_set);
2852  FD_ZERO (&err_set);
2853 
2854  for (i = 0; i < n_fds; i++)
2855  {
2856  DBusPollFD *fdp = &fds[i];
2857 
2858  if (fdp->events & _DBUS_POLLIN)
2859  FD_SET (fdp->fd, &read_set);
2860 
2861  if (fdp->events & _DBUS_POLLOUT)
2862  FD_SET (fdp->fd, &write_set);
2863 
2864  FD_SET (fdp->fd, &err_set);
2865 
2866  max_fd = MAX (max_fd, fdp->fd);
2867  }
2868 
2869  tv.tv_sec = timeout_milliseconds / 1000;
2870  tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2871 
2872  ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2873  timeout_milliseconds < 0 ? NULL : &tv);
2874 
2875  if (ready > 0)
2876  {
2877  for (i = 0; i < n_fds; i++)
2878  {
2879  DBusPollFD *fdp = &fds[i];
2880 
2881  fdp->revents = 0;
2882 
2883  if (FD_ISSET (fdp->fd, &read_set))
2884  fdp->revents |= _DBUS_POLLIN;
2885 
2886  if (FD_ISSET (fdp->fd, &write_set))
2887  fdp->revents |= _DBUS_POLLOUT;
2888 
2889  if (FD_ISSET (fdp->fd, &err_set))
2890  fdp->revents |= _DBUS_POLLERR;
2891  }
2892  }
2893 
2894  return ready;
2895 #endif
2896 }
2897 
2905 void
2907  long *tv_usec)
2908 {
2909 #ifdef HAVE_MONOTONIC_CLOCK
2910  struct timespec ts;
2911  clock_gettime (CLOCK_MONOTONIC, &ts);
2912 
2913  if (tv_sec)
2914  *tv_sec = ts.tv_sec;
2915  if (tv_usec)
2916  *tv_usec = ts.tv_nsec / 1000;
2917 #else
2918  struct timeval t;
2919 
2920  gettimeofday (&t, NULL);
2921 
2922  if (tv_sec)
2923  *tv_sec = t.tv_sec;
2924  if (tv_usec)
2925  *tv_usec = t.tv_usec;
2926 #endif
2927 }
2928 
2936 void
2937 _dbus_get_real_time (long *tv_sec,
2938  long *tv_usec)
2939 {
2940  struct timeval t;
2941 
2942  gettimeofday (&t, NULL);
2943 
2944  if (tv_sec)
2945  *tv_sec = t.tv_sec;
2946  if (tv_usec)
2947  *tv_usec = t.tv_usec;
2948 }
2949 
2960  DBusError *error)
2961 {
2962  const char *filename_c;
2963 
2964  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2965 
2966  filename_c = _dbus_string_get_const_data (filename);
2967 
2968  if (mkdir (filename_c, 0700) < 0)
2969  {
2970  if (errno == EEXIST)
2971  return TRUE;
2972 
2974  "Failed to create directory %s: %s\n",
2975  filename_c, _dbus_strerror (errno));
2976  return FALSE;
2977  }
2978  else
2979  return TRUE;
2980 }
2981 
2992  DBusError *error)
2993 {
2994  const char *filename_c;
2995 
2996  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2997 
2998  filename_c = _dbus_string_get_const_data (filename);
2999 
3000  if (mkdir (filename_c, 0700) < 0)
3001  {
3003  "Failed to create directory %s: %s\n",
3004  filename_c, _dbus_strerror (errno));
3005  return FALSE;
3006  }
3007  else
3008  return TRUE;
3009 }
3010 
3023  const DBusString *next_component)
3024 {
3025  dbus_bool_t dir_ends_in_slash;
3026  dbus_bool_t file_starts_with_slash;
3027 
3028  if (_dbus_string_get_length (dir) == 0 ||
3029  _dbus_string_get_length (next_component) == 0)
3030  return TRUE;
3031 
3032  dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
3033  _dbus_string_get_length (dir) - 1);
3034 
3035  file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
3036 
3037  if (dir_ends_in_slash && file_starts_with_slash)
3038  {
3039  _dbus_string_shorten (dir, 1);
3040  }
3041  else if (!(dir_ends_in_slash || file_starts_with_slash))
3042  {
3043  if (!_dbus_string_append_byte (dir, '/'))
3044  return FALSE;
3045  }
3046 
3047  return _dbus_string_copy (next_component, 0, dir,
3048  _dbus_string_get_length (dir));
3049 }
3050 
3052 #define NANOSECONDS_PER_SECOND 1000000000
3053 
3054 #define MICROSECONDS_PER_SECOND 1000000
3055 
3056 #define MILLISECONDS_PER_SECOND 1000
3057 
3058 #define NANOSECONDS_PER_MILLISECOND 1000000
3059 
3060 #define MICROSECONDS_PER_MILLISECOND 1000
3061 
3066 void
3067 _dbus_sleep_milliseconds (int milliseconds)
3068 {
3069 #ifdef HAVE_NANOSLEEP
3070  struct timespec req;
3071  struct timespec rem;
3072 
3073  req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
3074  req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
3075  rem.tv_sec = 0;
3076  rem.tv_nsec = 0;
3077 
3078  while (nanosleep (&req, &rem) < 0 && errno == EINTR)
3079  req = rem;
3080 #elif defined (HAVE_USLEEP)
3081  usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
3082 #else /* ! HAVE_USLEEP */
3083  sleep (MAX (milliseconds / 1000, 1));
3084 #endif
3085 }
3086 
3098  int n_bytes,
3099  DBusError *error)
3100 {
3101  int old_len;
3102  int fd;
3103  int result;
3104 
3105  old_len = _dbus_string_get_length (str);
3106  fd = -1;
3107 
3108  /* note, urandom on linux will fall back to pseudorandom */
3109  fd = open ("/dev/urandom", O_RDONLY);
3110 
3111  if (fd < 0)
3112  {
3113  dbus_set_error (error, _dbus_error_from_errno (errno),
3114  "Could not open /dev/urandom: %s",
3115  _dbus_strerror (errno));
3116  return FALSE;
3117  }
3118 
3119  _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3120 
3121  result = _dbus_read (fd, str, n_bytes);
3122 
3123  if (result != n_bytes)
3124  {
3125  if (result < 0)
3126  dbus_set_error (error, _dbus_error_from_errno (errno),
3127  "Could not read /dev/urandom: %s",
3128  _dbus_strerror (errno));
3129  else
3131  "Short read from /dev/urandom");
3132 
3133  _dbus_close (fd, NULL);
3134  _dbus_string_set_length (str, old_len);
3135  return FALSE;
3136  }
3137 
3138  _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3139  n_bytes);
3140 
3141  _dbus_close (fd, NULL);
3142 
3143  return TRUE;
3144 }
3145 
3151 void
3152 _dbus_exit (int code)
3153 {
3154  _exit (code);
3155 }
3156 
3165 const char*
3166 _dbus_strerror (int error_number)
3167 {
3168  const char *msg;
3169 
3170  msg = strerror (error_number);
3171  if (msg == NULL)
3172  msg = "unknown";
3173 
3174  return msg;
3175 }
3176 
3180 void
3182 {
3183  signal (SIGPIPE, SIG_IGN);
3184 }
3185 
3193 void
3195 {
3196  int val;
3197 
3198  val = fcntl (fd, F_GETFD, 0);
3199 
3200  if (val < 0)
3201  return;
3202 
3203  val |= FD_CLOEXEC;
3204 
3205  fcntl (fd, F_SETFD, val);
3206 }
3207 
3216 _dbus_close (int fd,
3217  DBusError *error)
3218 {
3219  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3220 
3221  again:
3222  if (close (fd) < 0)
3223  {
3224  if (errno == EINTR)
3225  goto again;
3226 
3227  dbus_set_error (error, _dbus_error_from_errno (errno),
3228  "Could not close fd %d", fd);
3229  return FALSE;
3230  }
3231 
3232  return TRUE;
3233 }
3234 
3243 int
3244 _dbus_dup(int fd,
3245  DBusError *error)
3246 {
3247  int new_fd;
3248 
3249 #ifdef F_DUPFD_CLOEXEC
3250  dbus_bool_t cloexec_done;
3251 
3252  new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3253  cloexec_done = new_fd >= 0;
3254 
3255  if (new_fd < 0 && errno == EINVAL)
3256 #endif
3257  {
3258  new_fd = fcntl(fd, F_DUPFD, 3);
3259  }
3260 
3261  if (new_fd < 0) {
3262 
3263  dbus_set_error (error, _dbus_error_from_errno (errno),
3264  "Could not duplicate fd %d", fd);
3265  return -1;
3266  }
3267 
3268 #ifdef F_DUPFD_CLOEXEC
3269  if (!cloexec_done)
3270 #endif
3271  {
3273  }
3274 
3275  return new_fd;
3276 }
3277 
3287  DBusError *error)
3288 {
3289  return _dbus_set_fd_nonblocking (fd.fd, error);
3290 }
3291 
3292 static dbus_bool_t
3293 _dbus_set_fd_nonblocking (int fd,
3294  DBusError *error)
3295 {
3296  int val;
3297 
3298  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3299 
3300  val = fcntl (fd, F_GETFL, 0);
3301  if (val < 0)
3302  {
3303  dbus_set_error (error, _dbus_error_from_errno (errno),
3304  "Failed to get flags from file descriptor %d: %s",
3305  fd, _dbus_strerror (errno));
3306  _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3307  _dbus_strerror (errno));
3308  return FALSE;
3309  }
3310 
3311  if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3312  {
3313  dbus_set_error (error, _dbus_error_from_errno (errno),
3314  "Failed to set nonblocking flag of file descriptor %d: %s",
3315  fd, _dbus_strerror (errno));
3316  _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3317  fd, _dbus_strerror (errno));
3318 
3319  return FALSE;
3320  }
3321 
3322  return TRUE;
3323 }
3324 
3330 void
3332 {
3333 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3334  void *bt[500];
3335  int bt_size;
3336  int i;
3337  char **syms;
3338 
3339  bt_size = backtrace (bt, 500);
3340 
3341  syms = backtrace_symbols (bt, bt_size);
3342 
3343  i = 0;
3344  while (i < bt_size)
3345  {
3346  /* don't use dbus_warn since it can _dbus_abort() */
3347  fprintf (stderr, " %s\n", syms[i]);
3348  ++i;
3349  }
3350  fflush (stderr);
3351 
3352  free (syms);
3353 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3354  fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3355 #else
3356  fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3357 #endif
3358 }
3359 
3374  DBusSocket *fd2,
3375  dbus_bool_t blocking,
3376  DBusError *error)
3377 {
3378 #ifdef HAVE_SOCKETPAIR
3379  int fds[2];
3380  int retval;
3381 
3382 #ifdef SOCK_CLOEXEC
3383  dbus_bool_t cloexec_done;
3384 
3385  retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3386  cloexec_done = retval >= 0;
3387 
3388  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3389 #endif
3390  {
3391  retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3392  }
3393 
3394  if (retval < 0)
3395  {
3396  dbus_set_error (error, _dbus_error_from_errno (errno),
3397  "Could not create full-duplex pipe");
3398  return FALSE;
3399  }
3400 
3401  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3402 
3403 #ifdef SOCK_CLOEXEC
3404  if (!cloexec_done)
3405 #endif
3406  {
3407  _dbus_fd_set_close_on_exec (fds[0]);
3408  _dbus_fd_set_close_on_exec (fds[1]);
3409  }
3410 
3411  if (!blocking &&
3412  (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3413  !_dbus_set_fd_nonblocking (fds[1], NULL)))
3414  {
3415  dbus_set_error (error, _dbus_error_from_errno (errno),
3416  "Could not set full-duplex pipe nonblocking");
3417 
3418  _dbus_close (fds[0], NULL);
3419  _dbus_close (fds[1], NULL);
3420 
3421  return FALSE;
3422  }
3423 
3424  fd1->fd = fds[0];
3425  fd2->fd = fds[1];
3426 
3427  _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3428  fd1->fd, fd2->fd);
3429 
3430  return TRUE;
3431 #else
3432  _dbus_warn ("_dbus_socketpair() not implemented on this OS\n");
3434  "_dbus_socketpair() not implemented on this OS");
3435  return FALSE;
3436 #endif
3437 }
3438 
3447 int
3449  va_list args)
3450 {
3451  char static_buf[1024];
3452  int bufsize = sizeof (static_buf);
3453  int len;
3454  va_list args_copy;
3455 
3456  DBUS_VA_COPY (args_copy, args);
3457  len = vsnprintf (static_buf, bufsize, format, args_copy);
3458  va_end (args_copy);
3459 
3460  /* If vsnprintf() returned non-negative, then either the string fits in
3461  * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3462  * returns the number of characters that were needed, or this OS returns the
3463  * truncated length.
3464  *
3465  * We ignore the possibility that snprintf might just ignore the length and
3466  * overrun the buffer (64-bit Solaris 7), because that's pathological.
3467  * If your libc is really that bad, come back when you have a better one. */
3468  if (len == bufsize)
3469  {
3470  /* This could be the truncated length (Tru64 and IRIX have this bug),
3471  * or the real length could be coincidentally the same. Which is it?
3472  * If vsnprintf returns the truncated length, we'll go to the slow
3473  * path. */
3474  DBUS_VA_COPY (args_copy, args);
3475 
3476  if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3477  len = -1;
3478 
3479  va_end (args_copy);
3480  }
3481 
3482  /* If vsnprintf() returned negative, we have to do more work.
3483  * HP-UX returns negative. */
3484  while (len < 0)
3485  {
3486  char *buf;
3487 
3488  bufsize *= 2;
3489 
3490  buf = dbus_malloc (bufsize);
3491 
3492  if (buf == NULL)
3493  return -1;
3494 
3495  DBUS_VA_COPY (args_copy, args);
3496  len = vsnprintf (buf, bufsize, format, args_copy);
3497  va_end (args_copy);
3498 
3499  dbus_free (buf);
3500 
3501  /* If the reported length is exactly the buffer size, round up to the
3502  * next size, in case vsnprintf has been returning the truncated
3503  * length */
3504  if (len == bufsize)
3505  len = -1;
3506  }
3507 
3508  return len;
3509 }
3510 
3517 const char*
3519 {
3520  /* Protected by _DBUS_LOCK_sysdeps */
3521  static const char* tmpdir = NULL;
3522 
3523  if (!_DBUS_LOCK (sysdeps))
3524  return NULL;
3525 
3526  if (tmpdir == NULL)
3527  {
3528  /* TMPDIR is what glibc uses, then
3529  * glibc falls back to the P_tmpdir macro which
3530  * just expands to "/tmp"
3531  */
3532  if (tmpdir == NULL)
3533  tmpdir = getenv("TMPDIR");
3534 
3535  /* These two env variables are probably
3536  * broken, but maybe some OS uses them?
3537  */
3538  if (tmpdir == NULL)
3539  tmpdir = getenv("TMP");
3540  if (tmpdir == NULL)
3541  tmpdir = getenv("TEMP");
3542 
3543  /* And this is the sane fallback. */
3544  if (tmpdir == NULL)
3545  tmpdir = "/tmp";
3546  }
3547 
3548  _DBUS_UNLOCK (sysdeps);
3549 
3550  _dbus_assert(tmpdir != NULL);
3551 
3552  return tmpdir;
3553 }
3554 
3555 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3556 
3575 static dbus_bool_t
3576 _read_subprocess_line_argv (const char *progpath,
3577  dbus_bool_t path_fallback,
3578  char * const *argv,
3579  DBusString *result,
3580  DBusError *error)
3581 {
3582  int result_pipe[2] = { -1, -1 };
3583  int errors_pipe[2] = { -1, -1 };
3584  pid_t pid;
3585  int ret;
3586  int status;
3587  int orig_len;
3588 
3589  dbus_bool_t retval;
3590  sigset_t new_set, old_set;
3591 
3592  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3593  retval = FALSE;
3594 
3595  /* We need to block any existing handlers for SIGCHLD temporarily; they
3596  * will cause waitpid() below to fail.
3597  * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3598  */
3599  sigemptyset (&new_set);
3600  sigaddset (&new_set, SIGCHLD);
3601  sigprocmask (SIG_BLOCK, &new_set, &old_set);
3602 
3603  orig_len = _dbus_string_get_length (result);
3604 
3605 #define READ_END 0
3606 #define WRITE_END 1
3607  if (pipe (result_pipe) < 0)
3608  {
3609  dbus_set_error (error, _dbus_error_from_errno (errno),
3610  "Failed to create a pipe to call %s: %s",
3611  progpath, _dbus_strerror (errno));
3612  _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3613  progpath, _dbus_strerror (errno));
3614  goto out;
3615  }
3616  if (pipe (errors_pipe) < 0)
3617  {
3618  dbus_set_error (error, _dbus_error_from_errno (errno),
3619  "Failed to create a pipe to call %s: %s",
3620  progpath, _dbus_strerror (errno));
3621  _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3622  progpath, _dbus_strerror (errno));
3623  goto out;
3624  }
3625 
3626  pid = fork ();
3627  if (pid < 0)
3628  {
3629  dbus_set_error (error, _dbus_error_from_errno (errno),
3630  "Failed to fork() to call %s: %s",
3631  progpath, _dbus_strerror (errno));
3632  _dbus_verbose ("Failed to fork() to call %s: %s\n",
3633  progpath, _dbus_strerror (errno));
3634  goto out;
3635  }
3636 
3637  if (pid == 0)
3638  {
3639  /* child process */
3640  int fd;
3641 
3642  fd = open ("/dev/null", O_RDWR);
3643  if (fd == -1)
3644  /* huh?! can't open /dev/null? */
3645  _exit (1);
3646 
3647  _dbus_verbose ("/dev/null fd %d opened\n", fd);
3648 
3649  /* set-up stdXXX */
3650  close (result_pipe[READ_END]);
3651  close (errors_pipe[READ_END]);
3652 
3653  if (dup2 (fd, 0) == -1) /* setup stdin */
3654  _exit (1);
3655  if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3656  _exit (1);
3657  if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3658  _exit (1);
3659 
3660  _dbus_close_all ();
3661 
3662  sigprocmask (SIG_SETMASK, &old_set, NULL);
3663 
3664  /* If it looks fully-qualified, try execv first */
3665  if (progpath[0] == '/')
3666  {
3667  execv (progpath, argv);
3668  /* Ok, that failed. Now if path_fallback is given, let's
3669  * try unqualified. This is mostly a hack to work
3670  * around systems which ship dbus-launch in /usr/bin
3671  * but everything else in /bin (because dbus-launch
3672  * depends on X11).
3673  */
3674  if (path_fallback)
3675  /* We must have a slash, because we checked above */
3676  execvp (strrchr (progpath, '/')+1, argv);
3677  }
3678  else
3679  execvp (progpath, argv);
3680 
3681  /* still nothing, we failed */
3682  _exit (1);
3683  }
3684 
3685  /* parent process */
3686  close (result_pipe[WRITE_END]);
3687  close (errors_pipe[WRITE_END]);
3688  result_pipe[WRITE_END] = -1;
3689  errors_pipe[WRITE_END] = -1;
3690 
3691  ret = 0;
3692  do
3693  {
3694  ret = _dbus_read (result_pipe[READ_END], result, 1024);
3695  }
3696  while (ret > 0);
3697 
3698  /* reap the child process to avoid it lingering as zombie */
3699  do
3700  {
3701  ret = waitpid (pid, &status, 0);
3702  }
3703  while (ret == -1 && errno == EINTR);
3704 
3705  /* We succeeded if the process exited with status 0 and
3706  anything was read */
3707  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3708  {
3709  /* The process ended with error */
3710  DBusString error_message;
3711  if (!_dbus_string_init (&error_message))
3712  {
3713  _DBUS_SET_OOM (error);
3714  goto out;
3715  }
3716 
3717  ret = 0;
3718  do
3719  {
3720  ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3721  }
3722  while (ret > 0);
3723 
3724  _dbus_string_set_length (result, orig_len);
3725  if (_dbus_string_get_length (&error_message) > 0)
3727  "%s terminated abnormally with the following error: %s",
3728  progpath, _dbus_string_get_data (&error_message));
3729  else
3731  "%s terminated abnormally without any error message",
3732  progpath);
3733  goto out;
3734  }
3735 
3736  retval = TRUE;
3737 
3738  out:
3739  sigprocmask (SIG_SETMASK, &old_set, NULL);
3740 
3741  if (retval)
3742  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3743  else
3744  _DBUS_ASSERT_ERROR_IS_SET (error);
3745 
3746  if (result_pipe[0] != -1)
3747  close (result_pipe[0]);
3748  if (result_pipe[1] != -1)
3749  close (result_pipe[1]);
3750  if (errors_pipe[0] != -1)
3751  close (errors_pipe[0]);
3752  if (errors_pipe[1] != -1)
3753  close (errors_pipe[1]);
3754 
3755  return retval;
3756 }
3757 #endif
3758 
3772 _dbus_get_autolaunch_address (const char *scope,
3773  DBusString *address,
3774  DBusError *error)
3775 {
3776 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3777  /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3778  * but that's done elsewhere, and if it worked, this function wouldn't
3779  * be called.) */
3780  const char *display;
3781  const char *progpath;
3782  char *argv[6];
3783  int i;
3784  DBusString uuid;
3785  dbus_bool_t retval;
3786 
3787  if (_dbus_check_setuid ())
3788  {
3790  "Unable to autolaunch when setuid");
3791  return FALSE;
3792  }
3793 
3794  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3795  retval = FALSE;
3796 
3797  /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3798  * dbus-launch-x11 is just going to fail. Rather than trying to
3799  * run it, we might as well bail out early with a nice error.
3800  *
3801  * This is not strictly true in a world where the user bus exists,
3802  * because dbus-launch --autolaunch knows how to connect to that -
3803  * but if we were going to connect to the user bus, we'd have done
3804  * so before trying autolaunch: in any case. */
3805  display = _dbus_getenv ("DISPLAY");
3806 
3807  if (display == NULL || display[0] == '\0')
3808  {
3810  "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3811  return FALSE;
3812  }
3813 
3814  if (!_dbus_string_init (&uuid))
3815  {
3816  _DBUS_SET_OOM (error);
3817  return FALSE;
3818  }
3819 
3820  if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3821  {
3822  goto out;
3823  }
3824 
3825 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3826  progpath = _dbus_getenv ("DBUS_TEST_DBUS_LAUNCH");
3827 
3828  if (progpath == NULL)
3829 #endif
3830  progpath = DBUS_BINDIR "/dbus-launch";
3831  /*
3832  * argv[0] is always dbus-launch, that's the name what we'll
3833  * get from /proc, or ps(1), regardless what the progpath is,
3834  * see fd.o#69716
3835  */
3836  i = 0;
3837  argv[i] = "dbus-launch";
3838  ++i;
3839  argv[i] = "--autolaunch";
3840  ++i;
3841  argv[i] = _dbus_string_get_data (&uuid);
3842  ++i;
3843  argv[i] = "--binary-syntax";
3844  ++i;
3845  argv[i] = "--close-stderr";
3846  ++i;
3847  argv[i] = NULL;
3848  ++i;
3849 
3850  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3851 
3852  retval = _read_subprocess_line_argv (progpath,
3853  TRUE,
3854  argv, address, error);
3855 
3856  out:
3857  _dbus_string_free (&uuid);
3858  return retval;
3859 #else
3861  "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3862  "set your DBUS_SESSION_BUS_ADDRESS instead");
3863  return FALSE;
3864 #endif
3865 }
3866 
3887  dbus_bool_t create_if_not_found,
3888  DBusError *error)
3889 {
3890  DBusString filename;
3891  dbus_bool_t b;
3892 
3893  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3894 
3895  b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3896  if (b)
3897  return TRUE;
3898 
3899  dbus_error_free (error);
3900 
3901  /* Fallback to the system machine ID */
3902  _dbus_string_init_const (&filename, "/etc/machine-id");
3903  b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3904 
3905  if (b)
3906  {
3907  /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3908  * complain if that isn't possible for whatever reason */
3909  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3910  _dbus_write_uuid_file (&filename, machine_id, NULL);
3911 
3912  return TRUE;
3913  }
3914 
3915  if (!create_if_not_found)
3916  return FALSE;
3917 
3918  /* if none found, try to make a new one */
3919  dbus_error_free (error);
3920  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3921 
3922  if (!_dbus_generate_uuid (machine_id, error))
3923  return FALSE;
3924 
3925  return _dbus_write_uuid_file (&filename, machine_id, error);
3926 }
3927 
3937  const char *launchd_env_var,
3938  DBusError *error)
3939 {
3940 #ifdef DBUS_ENABLE_LAUNCHD
3941  char *argv[4];
3942  int i;
3943 
3944  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3945 
3946  if (_dbus_check_setuid ())
3947  {
3949  "Unable to find launchd socket when setuid");
3950  return FALSE;
3951  }
3952 
3953  i = 0;
3954  argv[i] = "launchctl";
3955  ++i;
3956  argv[i] = "getenv";
3957  ++i;
3958  argv[i] = (char*)launchd_env_var;
3959  ++i;
3960  argv[i] = NULL;
3961  ++i;
3962 
3963  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3964 
3965  if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3966  {
3967  return FALSE;
3968  }
3969 
3970  /* no error, but no result either */
3971  if (_dbus_string_get_length(socket_path) == 0)
3972  {
3973  return FALSE;
3974  }
3975 
3976  /* strip the carriage-return */
3977  _dbus_string_shorten(socket_path, 1);
3978  return TRUE;
3979 #else /* DBUS_ENABLE_LAUNCHD */
3981  "can't lookup socket from launchd; launchd support not compiled in");
3982  return FALSE;
3983 #endif
3984 }
3985 
3986 #ifdef DBUS_ENABLE_LAUNCHD
3987 static dbus_bool_t
3988 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
3989 {
3990  dbus_bool_t valid_socket;
3991  DBusString socket_path;
3992 
3993  if (_dbus_check_setuid ())
3994  {
3996  "Unable to find launchd socket when setuid");
3997  return FALSE;
3998  }
3999 
4000  if (!_dbus_string_init (&socket_path))
4001  {
4002  _DBUS_SET_OOM (error);
4003  return FALSE;
4004  }
4005 
4006  valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
4007 
4008  if (dbus_error_is_set(error))
4009  {
4010  _dbus_string_free(&socket_path);
4011  return FALSE;
4012  }
4013 
4014  if (!valid_socket)
4015  {
4016  dbus_set_error(error, "no socket path",
4017  "launchd did not provide a socket path, "
4018  "verify that org.freedesktop.dbus-session.plist is loaded!");
4019  _dbus_string_free(&socket_path);
4020  return FALSE;
4021  }
4022  if (!_dbus_string_append (address, "unix:path="))
4023  {
4024  _DBUS_SET_OOM (error);
4025  _dbus_string_free(&socket_path);
4026  return FALSE;
4027  }
4028  if (!_dbus_string_copy (&socket_path, 0, address,
4029  _dbus_string_get_length (address)))
4030  {
4031  _DBUS_SET_OOM (error);
4032  _dbus_string_free(&socket_path);
4033  return FALSE;
4034  }
4035 
4036  _dbus_string_free(&socket_path);
4037  return TRUE;
4038 }
4039 #endif
4040 
4042 _dbus_lookup_user_bus (dbus_bool_t *supported,
4043  DBusString *address,
4044  DBusError *error)
4045 {
4046  const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
4047  dbus_bool_t ret = FALSE;
4048  struct stat stbuf;
4049  DBusString user_bus_path;
4050 
4051  if (runtime_dir == NULL)
4052  {
4053  _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
4054  *supported = FALSE;
4055  return TRUE; /* Cannot use it, but not an error */
4056  }
4057 
4058  if (!_dbus_string_init (&user_bus_path))
4059  {
4060  _DBUS_SET_OOM (error);
4061  return FALSE;
4062  }
4063 
4064  if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
4065  {
4066  _DBUS_SET_OOM (error);
4067  goto out;
4068  }
4069 
4070  if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
4071  {
4072  _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
4073  _dbus_strerror (errno));
4074  *supported = FALSE;
4075  ret = TRUE; /* Cannot use it, but not an error */
4076  goto out;
4077  }
4078 
4079  if (stbuf.st_uid != getuid ())
4080  {
4081  _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
4082  (long) stbuf.st_uid, (long) getuid ());
4083  *supported = FALSE;
4084  ret = TRUE; /* Cannot use it, but not an error */
4085  goto out;
4086  }
4087 
4088  if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
4089  {
4090  _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
4091  (long) stbuf.st_mode);
4092  *supported = FALSE;
4093  ret = TRUE; /* Cannot use it, but not an error */
4094  goto out;
4095  }
4096 
4097  if (!_dbus_string_append (address, "unix:path=") ||
4098  !_dbus_address_append_escaped (address, &user_bus_path))
4099  {
4100  _DBUS_SET_OOM (error);
4101  goto out;
4102  }
4103 
4104  *supported = TRUE;
4105  ret = TRUE;
4106 
4107 out:
4108  _dbus_string_free (&user_bus_path);
4109  return ret;
4110 }
4111 
4133  DBusString *address,
4134  DBusError *error)
4135 {
4136 #ifdef DBUS_ENABLE_LAUNCHD
4137  *supported = TRUE;
4138  return _dbus_lookup_session_address_launchd (address, error);
4139 #else
4140  *supported = FALSE;
4141 
4142  if (!_dbus_lookup_user_bus (supported, address, error))
4143  return FALSE;
4144  else if (*supported)
4145  return TRUE;
4146 
4147  /* On non-Mac Unix platforms, if the session address isn't already
4148  * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4149  * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4150  * autolaunch: global default; see init_session_address in
4151  * dbus/dbus-bus.c. */
4152  return TRUE;
4153 #endif
4154 }
4155 
4163 void
4165 {
4167 }
4168 
4184  DBusCredentials *credentials)
4185 {
4186  DBusString homedir;
4187  DBusString dotdir;
4188  dbus_uid_t uid;
4189 
4190  _dbus_assert (credentials != NULL);
4192 
4193  if (!_dbus_string_init (&homedir))
4194  return FALSE;
4195 
4196  uid = _dbus_credentials_get_unix_uid (credentials);
4197  _dbus_assert (uid != DBUS_UID_UNSET);
4198 
4199  if (!_dbus_homedir_from_uid (uid, &homedir))
4200  goto failed;
4201 
4202 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4203  {
4204  const char *override;
4205 
4206  override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4207  if (override != NULL && *override != '\0')
4208  {
4209  _dbus_string_set_length (&homedir, 0);
4210  if (!_dbus_string_append (&homedir, override))
4211  goto failed;
4212 
4213  _dbus_verbose ("Using fake homedir for testing: %s\n",
4214  _dbus_string_get_const_data (&homedir));
4215  }
4216  else
4217  {
4218  /* Not strictly thread-safe, but if we fail at thread-safety here,
4219  * the worst that will happen is some extra warnings. */
4220  static dbus_bool_t already_warned = FALSE;
4221  if (!already_warned)
4222  {
4223  _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
4224  already_warned = TRUE;
4225  }
4226  }
4227  }
4228 #endif
4229 
4230  _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4231  if (!_dbus_concat_dir_and_file (&homedir,
4232  &dotdir))
4233  goto failed;
4234 
4235  if (!_dbus_string_copy (&homedir, 0,
4236  directory, _dbus_string_get_length (directory))) {
4237  goto failed;
4238  }
4239 
4240  _dbus_string_free (&homedir);
4241  return TRUE;
4242 
4243  failed:
4244  _dbus_string_free (&homedir);
4245  return FALSE;
4246 }
4247 
4248 //PENDING(kdab) docs
4250 _dbus_daemon_publish_session_bus_address (const char* addr,
4251  const char *scope)
4252 {
4253  return TRUE;
4254 }
4255 
4256 //PENDING(kdab) docs
4257 void
4258 _dbus_daemon_unpublish_session_bus_address (void)
4259 {
4260 
4261 }
4262 
4271 {
4272  return e == EAGAIN || e == EWOULDBLOCK;
4273 }
4274 
4284  DBusError *error)
4285 {
4286  const char *filename_c;
4287 
4288  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4289 
4290  filename_c = _dbus_string_get_const_data (filename);
4291 
4292  if (rmdir (filename_c) != 0)
4293  {
4295  "Failed to remove directory %s: %s\n",
4296  filename_c, _dbus_strerror (errno));
4297  return FALSE;
4298  }
4299 
4300  return TRUE;
4301 }
4302 
4312 {
4313 #ifdef SCM_RIGHTS
4314  union {
4315  struct sockaddr sa;
4316  struct sockaddr_storage storage;
4317  struct sockaddr_un un;
4318  } sa_buf;
4319 
4320  socklen_t sa_len = sizeof(sa_buf);
4321 
4322  _DBUS_ZERO(sa_buf);
4323 
4324  if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4325  return FALSE;
4326 
4327  return sa_buf.sa.sa_family == AF_UNIX;
4328 
4329 #else
4330  return FALSE;
4331 
4332 #endif
4333 }
4334 
4339 void
4341 {
4342  int maxfds, i;
4343 
4344 #ifdef __linux__
4345  DIR *d;
4346 
4347  /* On Linux we can optimize this a bit if /proc is available. If it
4348  isn't available, fall back to the brute force way. */
4349 
4350  d = opendir ("/proc/self/fd");
4351  if (d)
4352  {
4353  for (;;)
4354  {
4355  struct dirent buf, *de;
4356  int k, fd;
4357  long l;
4358  char *e = NULL;
4359 
4360  k = readdir_r (d, &buf, &de);
4361  if (k != 0 || !de)
4362  break;
4363 
4364  if (de->d_name[0] == '.')
4365  continue;
4366 
4367  errno = 0;
4368  l = strtol (de->d_name, &e, 10);
4369  if (errno != 0 || e == NULL || *e != '\0')
4370  continue;
4371 
4372  fd = (int) l;
4373  if (fd < 3)
4374  continue;
4375 
4376  if (fd == dirfd (d))
4377  continue;
4378 
4379  close (fd);
4380  }
4381 
4382  closedir (d);
4383  return;
4384  }
4385 #endif
4386 
4387  maxfds = sysconf (_SC_OPEN_MAX);
4388 
4389  /* Pick something reasonable if for some reason sysconf says
4390  * unlimited.
4391  */
4392  if (maxfds < 0)
4393  maxfds = 1024;
4394 
4395  /* close all inherited fds */
4396  for (i = 3; i < maxfds; i++)
4397  close (i);
4398 }
4399 
4411 {
4412  /* TODO: get __libc_enable_secure exported from glibc.
4413  * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4414  */
4415 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4416  {
4417  /* See glibc/include/unistd.h */
4418  extern int __libc_enable_secure;
4419  return __libc_enable_secure;
4420  }
4421 #elif defined(HAVE_ISSETUGID)
4422  /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4423  return issetugid ();
4424 #else
4425  uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4426  gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4427 
4428  /* We call into this function from _dbus_threads_init_platform_specific()
4429  * to make sure these are initialized before we start threading. */
4430  static dbus_bool_t check_setuid_initialised;
4431  static dbus_bool_t is_setuid;
4432 
4433  if (_DBUS_UNLIKELY (!check_setuid_initialised))
4434  {
4435 #ifdef HAVE_GETRESUID
4436  if (getresuid (&ruid, &euid, &suid) != 0 ||
4437  getresgid (&rgid, &egid, &sgid) != 0)
4438 #endif /* HAVE_GETRESUID */
4439  {
4440  suid = ruid = getuid ();
4441  sgid = rgid = getgid ();
4442  euid = geteuid ();
4443  egid = getegid ();
4444  }
4445 
4446  check_setuid_initialised = TRUE;
4447  is_setuid = (ruid != euid || ruid != suid ||
4448  rgid != egid || rgid != sgid);
4449 
4450  }
4451  return is_setuid;
4452 #endif
4453 }
4454 
4464  DBusString *address,
4465  DBusError *error)
4466 {
4467  union {
4468  struct sockaddr sa;
4469  struct sockaddr_storage storage;
4470  struct sockaddr_un un;
4471  struct sockaddr_in ipv4;
4472  struct sockaddr_in6 ipv6;
4473  } socket;
4474  char hostip[INET6_ADDRSTRLEN];
4475  int size = sizeof (socket);
4476  DBusString path_str;
4477 
4478  if (getsockname (fd.fd, &socket.sa, &size))
4479  goto err;
4480 
4481  switch (socket.sa.sa_family)
4482  {
4483  case AF_UNIX:
4484  if (socket.un.sun_path[0]=='\0')
4485  {
4486  _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4487  if (_dbus_string_append (address, "unix:abstract=") &&
4488  _dbus_address_append_escaped (address, &path_str))
4489  return TRUE;
4490  }
4491  else
4492  {
4493  _dbus_string_init_const (&path_str, socket.un.sun_path);
4494  if (_dbus_string_append (address, "unix:path=") &&
4495  _dbus_address_append_escaped (address, &path_str))
4496  return TRUE;
4497  }
4498  break;
4499  case AF_INET:
4500  if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4501  if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4502  hostip, ntohs (socket.ipv4.sin_port)))
4503  return TRUE;
4504  break;
4505 #ifdef AF_INET6
4506  case AF_INET6:
4507  _dbus_string_init_const (&path_str, hostip);
4508  if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4509  if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4510  ntohs (socket.ipv6.sin6_port)) &&
4511  _dbus_address_append_escaped (address, &path_str))
4512  return TRUE;
4513  break;
4514 #endif
4515  default:
4516  dbus_set_error (error,
4517  _dbus_error_from_errno (EINVAL),
4518  "Failed to read address from socket: Unknown socket type.");
4519  return FALSE;
4520  }
4521  err:
4522  dbus_set_error (error,
4523  _dbus_error_from_errno (errno),
4524  "Failed to open socket: %s",
4525  _dbus_strerror (errno));
4526  return FALSE;
4527 }
4528 
4529 int
4530 _dbus_save_socket_errno (void)
4531 {
4532  return errno;
4533 }
4534 
4535 void
4536 _dbus_restore_socket_errno (int saved_errno)
4537 {
4538  errno = saved_errno;
4539 }
4540 
4541 /* 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:435
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:279
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:392
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:284
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.
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
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:701
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:57
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:123
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:119
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.
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:349
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:388
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.
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:383
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:112
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:114
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:590
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:461
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:105
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
Socket interface.
Definition: dbus-sysdeps.h:148
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:461
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:392
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.
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().
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:116
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:382
#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.
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:873
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:121
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.
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.
#define FALSE
Expands to "0".
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.
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
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:875
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:109
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:601
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...
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:185
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:107
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
short revents
Events that occurred.
Definition: dbus-sysdeps.h:384
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:394