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