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