D-Bus  1.10.6
dbus-sysdeps-unix.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003, 2006 Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <config.h>
26 
27 #include "dbus-internals.h"
28 #include "dbus-sysdeps.h"
29 #include "dbus-sysdeps-unix.h"
30 #include "dbus-threads.h"
31 #include "dbus-protocol.h"
32 #include "dbus-file.h"
33 #include "dbus-transport.h"
34 #include "dbus-string.h"
35 #include "dbus-userdb.h"
36 #include "dbus-list.h"
37 #include "dbus-credentials.h"
38 #include "dbus-nonce.h"
39 
40 #include <sys/types.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <signal.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <fcntl.h>
47 #include <sys/socket.h>
48 #include <dirent.h>
49 #include <sys/un.h>
50 #include <pwd.h>
51 #include <time.h>
52 #include <locale.h>
53 #include <sys/time.h>
54 #include <sys/stat.h>
55 #include <sys/wait.h>
56 #include <netinet/in.h>
57 #include <netinet/tcp.h>
58 #include <netdb.h>
59 #include <grp.h>
60 #include <arpa/inet.h>
61 
62 #ifdef HAVE_ERRNO_H
63 #include <errno.h>
64 #endif
65 #ifdef HAVE_WRITEV
66 #include <sys/uio.h>
67 #endif
68 #ifdef HAVE_POLL
69 #include <sys/poll.h>
70 #endif
71 #ifdef HAVE_BACKTRACE
72 #include <execinfo.h>
73 #endif
74 #ifdef HAVE_GETPEERUCRED
75 #include <ucred.h>
76 #endif
77 #ifdef HAVE_ALLOCA_H
78 #include <alloca.h>
79 #endif
80 
81 #ifdef HAVE_ADT
82 #include <bsm/adt.h>
83 #endif
84 
85 #ifdef HAVE_SYSTEMD
86 #include <systemd/sd-daemon.h>
87 #endif
88 
89 #if !DBUS_USE_SYNC
90 #include <pthread.h>
91 #endif
92 
93 #ifndef O_BINARY
94 #define O_BINARY 0
95 #endif
96 
97 #ifndef AI_ADDRCONFIG
98 #define AI_ADDRCONFIG 0
99 #endif
100 
101 #ifndef HAVE_SOCKLEN_T
102 #define socklen_t int
103 #endif
104 
105 #if defined (__sun) || defined (__sun__)
106 /*
107  * CMS_SPACE etc. definitions for Solaris < 10, based on
108  * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html
109  * via
110  * http://wiki.opencsw.org/porting-faq#toc10
111  *
112  * These are only redefined for Solaris, for now: if your OS needs these too,
113  * please file a bug. (Or preferably, improve your OS so they're not needed.)
114  */
115 
116 # ifndef CMSG_ALIGN
117 # ifdef __sun__
118 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len)
119 # else
120  /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
121 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \
122  ~(sizeof (long) - 1))
123 # endif
124 # endif
125 
126 # ifndef CMSG_SPACE
127 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \
128  CMSG_ALIGN (len))
129 # endif
130 
131 # ifndef CMSG_LEN
132 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
133 # endif
134 
135 #endif /* Solaris */
136 
137 static dbus_bool_t _dbus_set_fd_nonblocking (int fd,
138  DBusError *error);
139 
140 static dbus_bool_t
141 _dbus_open_socket (int *fd_p,
142  int domain,
143  int type,
144  int protocol,
145  DBusError *error)
146 {
147 #ifdef SOCK_CLOEXEC
148  dbus_bool_t cloexec_done;
149 
150  *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol);
151  cloexec_done = *fd_p >= 0;
152 
153  /* Check if kernel seems to be too old to know SOCK_CLOEXEC */
154  if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE))
155 #endif
156  {
157  *fd_p = socket (domain, type, protocol);
158  }
159 
160  if (*fd_p >= 0)
161  {
162 #ifdef SOCK_CLOEXEC
163  if (!cloexec_done)
164 #endif
165  {
167  }
168 
169  _dbus_verbose ("socket fd %d opened\n", *fd_p);
170  return TRUE;
171  }
172  else
173  {
174  dbus_set_error(error,
175  _dbus_error_from_errno (errno),
176  "Failed to open socket: %s",
177  _dbus_strerror (errno));
178  return FALSE;
179  }
180 }
181 
192 static dbus_bool_t
193 _dbus_open_unix_socket (int *fd,
194  DBusError *error)
195 {
196  return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
197 }
198 
209  DBusError *error)
210 {
211  return _dbus_close (fd.fd, error);
212 }
213 
223 int
225  DBusString *buffer,
226  int count)
227 {
228  return _dbus_read (fd.fd, buffer, count);
229 }
230 
241 int
243  const DBusString *buffer,
244  int start,
245  int len)
246 {
247 #if HAVE_DECL_MSG_NOSIGNAL
248  const char *data;
249  int bytes_written;
250 
251  data = _dbus_string_get_const_data_len (buffer, start, len);
252 
253  again:
254 
255  bytes_written = send (fd.fd, data, len, MSG_NOSIGNAL);
256 
257  if (bytes_written < 0 && errno == EINTR)
258  goto again;
259 
260  return bytes_written;
261 
262 #else
263  return _dbus_write (fd.fd, buffer, start, len);
264 #endif
265 }
266 
279 int
281  DBusString *buffer,
282  int count,
283  int *fds,
284  int *n_fds) {
285 #ifndef HAVE_UNIX_FD_PASSING
286  int r;
287 
288  if ((r = _dbus_read_socket(fd, buffer, count)) < 0)
289  return r;
290 
291  *n_fds = 0;
292  return r;
293 
294 #else
295  int bytes_read;
296  int start;
297  struct msghdr m;
298  struct iovec iov;
299 
300  _dbus_assert (count >= 0);
301  _dbus_assert (*n_fds >= 0);
302 
303  start = _dbus_string_get_length (buffer);
304 
305  if (!_dbus_string_lengthen (buffer, count))
306  {
307  errno = ENOMEM;
308  return -1;
309  }
310 
311  _DBUS_ZERO(iov);
312  iov.iov_base = _dbus_string_get_data_len (buffer, start, count);
313  iov.iov_len = count;
314 
315  _DBUS_ZERO(m);
316  m.msg_iov = &iov;
317  m.msg_iovlen = 1;
318 
319  /* Hmm, we have no clue how long the control data will actually be
320  that is queued for us. The least we can do is assume that the
321  caller knows. Hence let's make space for the number of fds that
322  we shall read at max plus the cmsg header. */
323  m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int));
324 
325  /* It's probably safe to assume that systems with SCM_RIGHTS also
326  know alloca() */
327  m.msg_control = alloca(m.msg_controllen);
328  memset(m.msg_control, 0, m.msg_controllen);
329 
330  /* Do not include the padding at the end when we tell the kernel
331  * how much we're willing to receive. This avoids getting
332  * the padding filled with additional fds that we weren't expecting,
333  * if a (potentially malicious) sender included them. (fd.o #83622) */
334  m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
335 
336  again:
337 
338  bytes_read = recvmsg (fd.fd, &m, 0
339 #ifdef MSG_CMSG_CLOEXEC
340  |MSG_CMSG_CLOEXEC
341 #endif
342  );
343 
344  if (bytes_read < 0)
345  {
346  if (errno == EINTR)
347  goto again;
348  else
349  {
350  /* put length back (note that this doesn't actually realloc anything) */
351  _dbus_string_set_length (buffer, start);
352  return -1;
353  }
354  }
355  else
356  {
357  struct cmsghdr *cm;
358  dbus_bool_t found = FALSE;
359 
360  for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
361  if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
362  {
363  size_t i;
364  int *payload = (int *) CMSG_DATA (cm);
365  size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
366  size_t payload_len_fds = payload_len_bytes / sizeof (int);
367  size_t fds_to_use;
368 
369  /* Every non-negative int fits in a size_t without truncation,
370  * and we already know that *n_fds is non-negative, so
371  * casting (size_t) *n_fds is OK */
372  _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
373 
374  if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
375  {
376  /* The fds in the payload will fit in our buffer */
377  fds_to_use = payload_len_fds;
378  }
379  else
380  {
381  /* Too many fds in the payload. This shouldn't happen
382  * any more because we're setting m.msg_controllen to
383  * the exact number we can accept, but be safe and
384  * truncate. */
385  fds_to_use = (size_t) *n_fds;
386 
387  /* Close the excess fds to avoid DoS: if they stayed open,
388  * someone could send us an extra fd per message
389  * and we'd eventually run out. */
390  for (i = fds_to_use; i < payload_len_fds; i++)
391  {
392  close (payload[i]);
393  }
394  }
395 
396  memcpy (fds, payload, fds_to_use * sizeof (int));
397  found = TRUE;
398  /* This cannot overflow because we have chosen fds_to_use
399  * to be <= *n_fds */
400  *n_fds = (int) fds_to_use;
401 
402  /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
403  worked, hence we need to go through this list and set
404  CLOEXEC everywhere in any case */
405  for (i = 0; i < fds_to_use; i++)
407 
408  break;
409  }
410 
411  if (!found)
412  *n_fds = 0;
413 
414  if (m.msg_flags & MSG_CTRUNC)
415  {
416  int i;
417 
418  /* Hmm, apparently the control data was truncated. The bad
419  thing is that we might have completely lost a couple of fds
420  without chance to recover them. Hence let's treat this as a
421  serious error. */
422 
423  /* We still need to close whatever fds we *did* receive,
424  * otherwise they'll never get closed. (CVE-2020-12049) */
425  for (i = 0; i < *n_fds; i++)
426  close (fds[i]);
427 
428  *n_fds = 0;
429  errno = ENOSPC;
430  _dbus_string_set_length (buffer, start);
431  return -1;
432  }
433 
434  /* put length back (doesn't actually realloc) */
435  _dbus_string_set_length (buffer, start + bytes_read);
436 
437 #if 0
438  if (bytes_read > 0)
439  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
440 #endif
441 
442  return bytes_read;
443  }
444 #endif
445 }
446 
447 int
448 _dbus_write_socket_with_unix_fds(DBusSocket fd,
449  const DBusString *buffer,
450  int start,
451  int len,
452  const int *fds,
453  int n_fds) {
454 
455 #ifndef HAVE_UNIX_FD_PASSING
456 
457  if (n_fds > 0) {
458  errno = ENOTSUP;
459  return -1;
460  }
461 
462  return _dbus_write_socket(fd, buffer, start, len);
463 #else
464  return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds);
465 #endif
466 }
467 
468 int
469 _dbus_write_socket_with_unix_fds_two(DBusSocket fd,
470  const DBusString *buffer1,
471  int start1,
472  int len1,
473  const DBusString *buffer2,
474  int start2,
475  int len2,
476  const int *fds,
477  int n_fds) {
478 
479 #ifndef HAVE_UNIX_FD_PASSING
480 
481  if (n_fds > 0) {
482  errno = ENOTSUP;
483  return -1;
484  }
485 
486  return _dbus_write_socket_two(fd,
487  buffer1, start1, len1,
488  buffer2, start2, len2);
489 #else
490 
491  struct msghdr m;
492  struct cmsghdr *cm;
493  struct iovec iov[2];
494  int bytes_written;
495 
496  _dbus_assert (len1 >= 0);
497  _dbus_assert (len2 >= 0);
498  _dbus_assert (n_fds >= 0);
499 
500  _DBUS_ZERO(iov);
501  iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1);
502  iov[0].iov_len = len1;
503 
504  if (buffer2)
505  {
506  iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2);
507  iov[1].iov_len = len2;
508  }
509 
510  _DBUS_ZERO(m);
511  m.msg_iov = iov;
512  m.msg_iovlen = buffer2 ? 2 : 1;
513 
514  if (n_fds > 0)
515  {
516  m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int));
517  m.msg_control = alloca(m.msg_controllen);
518  memset(m.msg_control, 0, m.msg_controllen);
519 
520  cm = CMSG_FIRSTHDR(&m);
521  cm->cmsg_level = SOL_SOCKET;
522  cm->cmsg_type = SCM_RIGHTS;
523  cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int));
524  memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int));
525  }
526 
527  again:
528 
529  bytes_written = sendmsg (fd.fd, &m, 0
530 #if HAVE_DECL_MSG_NOSIGNAL
531  |MSG_NOSIGNAL
532 #endif
533  );
534 
535  if (bytes_written < 0 && errno == EINTR)
536  goto again;
537 
538 #if 0
539  if (bytes_written > 0)
540  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
541 #endif
542 
543  return bytes_written;
544 #endif
545 }
546 
560 int
562  const DBusString *buffer1,
563  int start1,
564  int len1,
565  const DBusString *buffer2,
566  int start2,
567  int len2)
568 {
569 #if HAVE_DECL_MSG_NOSIGNAL
570  struct iovec vectors[2];
571  const char *data1;
572  const char *data2;
573  int bytes_written;
574  struct msghdr m;
575 
576  _dbus_assert (buffer1 != NULL);
577  _dbus_assert (start1 >= 0);
578  _dbus_assert (start2 >= 0);
579  _dbus_assert (len1 >= 0);
580  _dbus_assert (len2 >= 0);
581 
582  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
583 
584  if (buffer2 != NULL)
585  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
586  else
587  {
588  data2 = NULL;
589  start2 = 0;
590  len2 = 0;
591  }
592 
593  vectors[0].iov_base = (char*) data1;
594  vectors[0].iov_len = len1;
595  vectors[1].iov_base = (char*) data2;
596  vectors[1].iov_len = len2;
597 
598  _DBUS_ZERO(m);
599  m.msg_iov = vectors;
600  m.msg_iovlen = data2 ? 2 : 1;
601 
602  again:
603 
604  bytes_written = sendmsg (fd.fd, &m, MSG_NOSIGNAL);
605 
606  if (bytes_written < 0 && errno == EINTR)
607  goto again;
608 
609  return bytes_written;
610 
611 #else
612  return _dbus_write_two (fd.fd, buffer1, start1, len1,
613  buffer2, start2, len2);
614 #endif
615 }
616 
633 int
634 _dbus_read (int fd,
635  DBusString *buffer,
636  int count)
637 {
638  int bytes_read;
639  int start;
640  char *data;
641 
642  _dbus_assert (count >= 0);
643 
644  start = _dbus_string_get_length (buffer);
645 
646  if (!_dbus_string_lengthen (buffer, count))
647  {
648  errno = ENOMEM;
649  return -1;
650  }
651 
652  data = _dbus_string_get_data_len (buffer, start, count);
653 
654  again:
655 
656  bytes_read = read (fd, data, count);
657 
658  if (bytes_read < 0)
659  {
660  if (errno == EINTR)
661  goto again;
662  else
663  {
664  /* put length back (note that this doesn't actually realloc anything) */
665  _dbus_string_set_length (buffer, start);
666  return -1;
667  }
668  }
669  else
670  {
671  /* put length back (doesn't actually realloc) */
672  _dbus_string_set_length (buffer, start + bytes_read);
673 
674 #if 0
675  if (bytes_read > 0)
676  _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
677 #endif
678 
679  return bytes_read;
680  }
681 }
682 
693 int
694 _dbus_write (int fd,
695  const DBusString *buffer,
696  int start,
697  int len)
698 {
699  const char *data;
700  int bytes_written;
701 
702  data = _dbus_string_get_const_data_len (buffer, start, len);
703 
704  again:
705 
706  bytes_written = write (fd, data, len);
707 
708  if (bytes_written < 0 && errno == EINTR)
709  goto again;
710 
711 #if 0
712  if (bytes_written > 0)
713  _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
714 #endif
715 
716  return bytes_written;
717 }
718 
739 int
741  const DBusString *buffer1,
742  int start1,
743  int len1,
744  const DBusString *buffer2,
745  int start2,
746  int len2)
747 {
748  _dbus_assert (buffer1 != NULL);
749  _dbus_assert (start1 >= 0);
750  _dbus_assert (start2 >= 0);
751  _dbus_assert (len1 >= 0);
752  _dbus_assert (len2 >= 0);
753 
754 #ifdef HAVE_WRITEV
755  {
756  struct iovec vectors[2];
757  const char *data1;
758  const char *data2;
759  int bytes_written;
760 
761  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
762 
763  if (buffer2 != NULL)
764  data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
765  else
766  {
767  data2 = NULL;
768  start2 = 0;
769  len2 = 0;
770  }
771 
772  vectors[0].iov_base = (char*) data1;
773  vectors[0].iov_len = len1;
774  vectors[1].iov_base = (char*) data2;
775  vectors[1].iov_len = len2;
776 
777  again:
778 
779  bytes_written = writev (fd,
780  vectors,
781  data2 ? 2 : 1);
782 
783  if (bytes_written < 0 && errno == EINTR)
784  goto again;
785 
786  return bytes_written;
787  }
788 #else /* HAVE_WRITEV */
789  {
790  int ret1, ret2;
791 
792  ret1 = _dbus_write (fd, buffer1, start1, len1);
793  if (ret1 == len1 && buffer2 != NULL)
794  {
795  ret2 = _dbus_write (fd, buffer2, start2, len2);
796  if (ret2 < 0)
797  ret2 = 0; /* we can't report an error as the first write was OK */
798 
799  return ret1 + ret2;
800  }
801  else
802  return ret1;
803  }
804 #endif /* !HAVE_WRITEV */
805 }
806 
807 #define _DBUS_MAX_SUN_PATH_LENGTH 99
808 
838 int
839 _dbus_connect_unix_socket (const char *path,
840  dbus_bool_t abstract,
841  DBusError *error)
842 {
843  int fd;
844  size_t path_len;
845  struct sockaddr_un addr;
846 
847  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
848 
849  _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
850  path, abstract);
851 
852 
853  if (!_dbus_open_unix_socket (&fd, error))
854  {
855  _DBUS_ASSERT_ERROR_IS_SET(error);
856  return -1;
857  }
858  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
859 
860  _DBUS_ZERO (addr);
861  addr.sun_family = AF_UNIX;
862  path_len = strlen (path);
863 
864  if (abstract)
865  {
866 #ifdef HAVE_ABSTRACT_SOCKETS
867  addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
868  path_len++; /* Account for the extra nul byte added to the start of sun_path */
869 
870  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
871  {
873  "Abstract socket name too long\n");
874  _dbus_close (fd, NULL);
875  return -1;
876  }
877 
878  strncpy (&addr.sun_path[1], path, path_len);
879  /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
880 #else /* HAVE_ABSTRACT_SOCKETS */
882  "Operating system does not support abstract socket namespace\n");
883  _dbus_close (fd, NULL);
884  return -1;
885 #endif /* ! HAVE_ABSTRACT_SOCKETS */
886  }
887  else
888  {
889  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
890  {
892  "Socket name too long\n");
893  _dbus_close (fd, NULL);
894  return -1;
895  }
896 
897  strncpy (addr.sun_path, path, path_len);
898  }
899 
900  if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
901  {
902  dbus_set_error (error,
903  _dbus_error_from_errno (errno),
904  "Failed to connect to socket %s: %s",
905  path, _dbus_strerror (errno));
906 
907  _dbus_close (fd, NULL);
908  return -1;
909  }
910 
911  if (!_dbus_set_fd_nonblocking (fd, error))
912  {
913  _DBUS_ASSERT_ERROR_IS_SET (error);
914 
915  _dbus_close (fd, NULL);
916  return -1;
917  }
918 
919  return fd;
920 }
921 
934 int
935 _dbus_connect_exec (const char *path,
936  char *const argv[],
937  DBusError *error)
938 {
939  int fds[2];
940  pid_t pid;
941  int retval;
942  dbus_bool_t cloexec_done = 0;
943 
944  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
945 
946  _dbus_verbose ("connecting to process %s\n", path);
947 
948 #ifdef SOCK_CLOEXEC
949  retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
950  cloexec_done = (retval >= 0);
951 
952  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
953 #endif
954  {
955  retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds);
956  }
957 
958  if (retval < 0)
959  {
960  dbus_set_error (error,
961  _dbus_error_from_errno (errno),
962  "Failed to create socket pair: %s",
963  _dbus_strerror (errno));
964  return -1;
965  }
966 
967  if (!cloexec_done)
968  {
971  }
972 
973  pid = fork ();
974  if (pid < 0)
975  {
976  dbus_set_error (error,
977  _dbus_error_from_errno (errno),
978  "Failed to fork() to call %s: %s",
979  path, _dbus_strerror (errno));
980  close (fds[0]);
981  close (fds[1]);
982  return -1;
983  }
984 
985  if (pid == 0)
986  {
987  /* child */
988  close (fds[0]);
989 
990  dup2 (fds[1], STDIN_FILENO);
991  dup2 (fds[1], STDOUT_FILENO);
992 
993  if (fds[1] != STDIN_FILENO &&
994  fds[1] != STDOUT_FILENO)
995  close (fds[1]);
996 
997  /* Inherit STDERR and the controlling terminal from the
998  parent */
999 
1000  _dbus_close_all ();
1001 
1002  execvp (path, argv);
1003 
1004  fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno));
1005 
1006  _exit(1);
1007  }
1008 
1009  /* parent */
1010  close (fds[1]);
1011 
1012  if (!_dbus_set_fd_nonblocking (fds[0], error))
1013  {
1014  _DBUS_ASSERT_ERROR_IS_SET (error);
1015 
1016  close (fds[0]);
1017  return -1;
1018  }
1019 
1020  return fds[0];
1021 }
1022 
1040 int
1041 _dbus_listen_unix_socket (const char *path,
1042  dbus_bool_t abstract,
1043  DBusError *error)
1044 {
1045  int listen_fd;
1046  struct sockaddr_un addr;
1047  size_t path_len;
1048 
1049  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1050 
1051  _dbus_verbose ("listening on unix socket %s abstract=%d\n",
1052  path, abstract);
1053 
1054  if (!_dbus_open_unix_socket (&listen_fd, error))
1055  {
1056  _DBUS_ASSERT_ERROR_IS_SET(error);
1057  return -1;
1058  }
1059  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1060 
1061  _DBUS_ZERO (addr);
1062  addr.sun_family = AF_UNIX;
1063  path_len = strlen (path);
1064 
1065  if (abstract)
1066  {
1067 #ifdef HAVE_ABSTRACT_SOCKETS
1068  /* remember that abstract names aren't nul-terminated so we rely
1069  * on sun_path being filled in with zeroes above.
1070  */
1071  addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
1072  path_len++; /* Account for the extra nul byte added to the start of sun_path */
1073 
1074  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1075  {
1077  "Abstract socket name too long\n");
1078  _dbus_close (listen_fd, NULL);
1079  return -1;
1080  }
1081 
1082  strncpy (&addr.sun_path[1], path, path_len);
1083  /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
1084 #else /* HAVE_ABSTRACT_SOCKETS */
1086  "Operating system does not support abstract socket namespace\n");
1087  _dbus_close (listen_fd, NULL);
1088  return -1;
1089 #endif /* ! HAVE_ABSTRACT_SOCKETS */
1090  }
1091  else
1092  {
1093  /* Discussed security implications of this with Nalin,
1094  * and we couldn't think of where it would kick our ass, but
1095  * it still seems a bit sucky. It also has non-security suckage;
1096  * really we'd prefer to exit if the socket is already in use.
1097  * But there doesn't seem to be a good way to do this.
1098  *
1099  * Just to be extra careful, I threw in the stat() - clearly
1100  * the stat() can't *fix* any security issue, but it at least
1101  * avoids inadvertent/accidental data loss.
1102  */
1103  {
1104  struct stat sb;
1105 
1106  if (stat (path, &sb) == 0 &&
1107  S_ISSOCK (sb.st_mode))
1108  unlink (path);
1109  }
1110 
1111  if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
1112  {
1114  "Socket name too long\n");
1115  _dbus_close (listen_fd, NULL);
1116  return -1;
1117  }
1118 
1119  strncpy (addr.sun_path, path, path_len);
1120  }
1121 
1122  if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
1123  {
1124  dbus_set_error (error, _dbus_error_from_errno (errno),
1125  "Failed to bind socket \"%s\": %s",
1126  path, _dbus_strerror (errno));
1127  _dbus_close (listen_fd, NULL);
1128  return -1;
1129  }
1130 
1131  if (listen (listen_fd, 30 /* backlog */) < 0)
1132  {
1133  dbus_set_error (error, _dbus_error_from_errno (errno),
1134  "Failed to listen on socket \"%s\": %s",
1135  path, _dbus_strerror (errno));
1136  _dbus_close (listen_fd, NULL);
1137  return -1;
1138  }
1139 
1140  if (!_dbus_set_fd_nonblocking (listen_fd, error))
1141  {
1142  _DBUS_ASSERT_ERROR_IS_SET (error);
1143  _dbus_close (listen_fd, NULL);
1144  return -1;
1145  }
1146 
1147  /* Try opening up the permissions, but if we can't, just go ahead
1148  * and continue, maybe it will be good enough.
1149  */
1150  if (!abstract && chmod (path, 0777) < 0)
1151  _dbus_warn ("Could not set mode 0777 on socket %s\n",
1152  path);
1153 
1154  return listen_fd;
1155 }
1156 
1167 int
1169  DBusError *error)
1170 {
1171 #ifdef HAVE_SYSTEMD
1172  int r, n;
1173  int fd;
1174  DBusSocket *new_fds;
1175 
1176  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1177 
1178  n = sd_listen_fds (TRUE);
1179  if (n < 0)
1180  {
1182  "Failed to acquire systemd socket: %s",
1183  _dbus_strerror (-n));
1184  return -1;
1185  }
1186 
1187  if (n <= 0)
1188  {
1190  "No socket received.");
1191  return -1;
1192  }
1193 
1194  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1195  {
1196  r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1);
1197  if (r < 0)
1198  {
1200  "Failed to verify systemd socket type: %s",
1201  _dbus_strerror (-r));
1202  return -1;
1203  }
1204 
1205  if (!r)
1206  {
1208  "Passed socket has wrong type.");
1209  return -1;
1210  }
1211  }
1212 
1213  /* OK, the file descriptors are all good, so let's take posession of
1214  them then. */
1215 
1216  new_fds = dbus_new (DBusSocket, n);
1217  if (!new_fds)
1218  {
1220  "Failed to allocate file handle array.");
1221  goto fail;
1222  }
1223 
1224  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1225  {
1226  if (!_dbus_set_fd_nonblocking (fd, error))
1227  {
1228  _DBUS_ASSERT_ERROR_IS_SET (error);
1229  goto fail;
1230  }
1231 
1232  new_fds[fd - SD_LISTEN_FDS_START].fd = fd;
1233  }
1234 
1235  *fds = new_fds;
1236  return n;
1237 
1238  fail:
1239 
1240  for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
1241  {
1242  _dbus_close (fd, NULL);
1243  }
1244 
1245  dbus_free (new_fds);
1246  return -1;
1247 #else
1249  "dbus was compiled without systemd support");
1250  return -1;
1251 #endif
1252 }
1253 
1267 DBusSocket
1268 _dbus_connect_tcp_socket (const char *host,
1269  const char *port,
1270  const char *family,
1271  DBusError *error)
1272 {
1273  return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error);
1274 }
1275 
1276 DBusSocket
1277 _dbus_connect_tcp_socket_with_nonce (const char *host,
1278  const char *port,
1279  const char *family,
1280  const char *noncefile,
1281  DBusError *error)
1282 {
1283  int saved_errno = 0;
1284  DBusSocket fd = DBUS_SOCKET_INIT;
1285  int res;
1286  struct addrinfo hints;
1287  struct addrinfo *ai, *tmp;
1288 
1289  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1290 
1291  _DBUS_ZERO (hints);
1292 
1293  if (!family)
1294  hints.ai_family = AF_UNSPEC;
1295  else if (!strcmp(family, "ipv4"))
1296  hints.ai_family = AF_INET;
1297  else if (!strcmp(family, "ipv6"))
1298  hints.ai_family = AF_INET6;
1299  else
1300  {
1301  dbus_set_error (error,
1303  "Unknown address family %s", family);
1304  return _dbus_socket_get_invalid ();
1305  }
1306  hints.ai_protocol = IPPROTO_TCP;
1307  hints.ai_socktype = SOCK_STREAM;
1308  hints.ai_flags = AI_ADDRCONFIG;
1309 
1310  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
1311  {
1312  dbus_set_error (error,
1313  _dbus_error_from_errno (errno),
1314  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1315  host, port, gai_strerror(res), res);
1316  return _dbus_socket_get_invalid ();
1317  }
1318 
1319  tmp = ai;
1320  while (tmp)
1321  {
1322  if (!_dbus_open_socket (&fd.fd, tmp->ai_family, SOCK_STREAM, 0, error))
1323  {
1324  freeaddrinfo(ai);
1325  _DBUS_ASSERT_ERROR_IS_SET(error);
1326  return _dbus_socket_get_invalid ();
1327  }
1328  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1329 
1330  if (connect (fd.fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1331  {
1332  saved_errno = errno;
1333  _dbus_close (fd.fd, NULL);
1334  fd.fd = -1;
1335  tmp = tmp->ai_next;
1336  continue;
1337  }
1338 
1339  break;
1340  }
1341  freeaddrinfo(ai);
1342 
1343  if (fd.fd == -1)
1344  {
1345  dbus_set_error (error,
1346  _dbus_error_from_errno (saved_errno),
1347  "Failed to connect to socket \"%s:%s\" %s",
1348  host, port, _dbus_strerror(saved_errno));
1349  return _dbus_socket_get_invalid ();
1350  }
1351 
1352  if (noncefile != NULL)
1353  {
1354  DBusString noncefileStr;
1355  dbus_bool_t ret;
1356  _dbus_string_init_const (&noncefileStr, noncefile);
1357  ret = _dbus_send_nonce (fd, &noncefileStr, error);
1358  _dbus_string_free (&noncefileStr);
1359 
1360  if (!ret)
1361  {
1362  _dbus_close (fd.fd, NULL);
1363  return _dbus_socket_get_invalid ();
1364  }
1365  }
1366 
1367  if (!_dbus_set_fd_nonblocking (fd.fd, error))
1368  {
1369  _dbus_close (fd.fd, NULL);
1370  return _dbus_socket_get_invalid ();
1371  }
1372 
1373  return fd;
1374 }
1375 
1392 int
1393 _dbus_listen_tcp_socket (const char *host,
1394  const char *port,
1395  const char *family,
1396  DBusString *retport,
1397  DBusSocket **fds_p,
1398  DBusError *error)
1399 {
1400  int saved_errno;
1401  int nlisten_fd = 0, res, i;
1402  DBusSocket *listen_fd = NULL;
1403  struct addrinfo hints;
1404  struct addrinfo *ai, *tmp;
1405  unsigned int reuseaddr;
1406 
1407  *fds_p = NULL;
1408  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1409 
1410  _DBUS_ZERO (hints);
1411 
1412  if (!family)
1413  hints.ai_family = AF_UNSPEC;
1414  else if (!strcmp(family, "ipv4"))
1415  hints.ai_family = AF_INET;
1416  else if (!strcmp(family, "ipv6"))
1417  hints.ai_family = AF_INET6;
1418  else
1419  {
1420  dbus_set_error (error,
1422  "Unknown address family %s", family);
1423  return -1;
1424  }
1425 
1426  hints.ai_protocol = IPPROTO_TCP;
1427  hints.ai_socktype = SOCK_STREAM;
1428  hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
1429 
1430  redo_lookup_with_port:
1431  ai = NULL;
1432  if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
1433  {
1434  dbus_set_error (error,
1435  _dbus_error_from_errno (errno),
1436  "Failed to lookup host/port: \"%s:%s\": %s (%d)",
1437  host ? host : "*", port, gai_strerror(res), res);
1438  goto failed;
1439  }
1440 
1441  tmp = ai;
1442  while (tmp)
1443  {
1444  int fd = -1, tcp_nodelay_on;
1445  DBusSocket *newlisten_fd;
1446 
1447  if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error))
1448  {
1449  _DBUS_ASSERT_ERROR_IS_SET(error);
1450  goto failed;
1451  }
1452  _DBUS_ASSERT_ERROR_IS_CLEAR(error);
1453 
1454  reuseaddr = 1;
1455  if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1)
1456  {
1457  _dbus_warn ("Failed to set socket option \"%s:%s\": %s",
1458  host ? host : "*", port, _dbus_strerror (errno));
1459  }
1460 
1461  /* Nagle's algorithm imposes a huge delay on the initial messages
1462  going over TCP. */
1463  tcp_nodelay_on = 1;
1464  if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &tcp_nodelay_on, sizeof (tcp_nodelay_on)) == -1)
1465  {
1466  _dbus_warn ("Failed to set TCP_NODELAY socket option \"%s:%s\": %s",
1467  host ? host : "*", port, _dbus_strerror (errno));
1468  }
1469 
1470  if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0)
1471  {
1472  saved_errno = errno;
1473  _dbus_close(fd, NULL);
1474  if (saved_errno == EADDRINUSE)
1475  {
1476  /* Depending on kernel policy, binding to an IPv6 address
1477  might implicitly bind to a corresponding IPv4
1478  address or vice versa, resulting in EADDRINUSE for the
1479  other one (e.g. bindv6only=0 on Linux).
1480 
1481  Also, after we "goto redo_lookup_with_port" after binding
1482  a port on one of the possible addresses, we will
1483  try to bind that same port on every address, including the
1484  same address again for a second time; that one will
1485  also fail with EADDRINUSE.
1486 
1487  For both those reasons, ignore EADDRINUSE here */
1488  tmp = tmp->ai_next;
1489  continue;
1490  }
1491  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1492  "Failed to bind socket \"%s:%s\": %s",
1493  host ? host : "*", port, _dbus_strerror (saved_errno));
1494  goto failed;
1495  }
1496 
1497  if (listen (fd, 30 /* backlog */) < 0)
1498  {
1499  saved_errno = errno;
1500  _dbus_close (fd, NULL);
1501  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1502  "Failed to listen on socket \"%s:%s\": %s",
1503  host ? host : "*", port, _dbus_strerror (saved_errno));
1504  goto failed;
1505  }
1506 
1507  newlisten_fd = dbus_realloc(listen_fd, sizeof(DBusSocket)*(nlisten_fd+1));
1508  if (!newlisten_fd)
1509  {
1510  saved_errno = errno;
1511  _dbus_close (fd, NULL);
1512  dbus_set_error (error, _dbus_error_from_errno (saved_errno),
1513  "Failed to allocate file handle array: %s",
1514  _dbus_strerror (saved_errno));
1515  goto failed;
1516  }
1517  listen_fd = newlisten_fd;
1518  listen_fd[nlisten_fd].fd = fd;
1519  nlisten_fd++;
1520 
1521  if (!_dbus_string_get_length(retport))
1522  {
1523  /* If the user didn't specify a port, or used 0, then
1524  the kernel chooses a port. After the first address
1525  is bound to, we need to force all remaining addresses
1526  to use the same port */
1527  if (!port || !strcmp(port, "0"))
1528  {
1529  int result;
1530  struct sockaddr_storage addr;
1531  socklen_t addrlen;
1532  char portbuf[50];
1533 
1534  addrlen = sizeof(addr);
1535  result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
1536 
1537  if (result == -1 ||
1538  (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
1539  portbuf, sizeof(portbuf),
1540  NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
1541  {
1542  dbus_set_error (error, _dbus_error_from_errno (errno),
1543  "Failed to resolve port \"%s:%s\": %s (%s)",
1544  host ? host : "*", port, gai_strerror(res), res);
1545  goto failed;
1546  }
1547  if (!_dbus_string_append(retport, portbuf))
1548  {
1550  goto failed;
1551  }
1552 
1553  /* Release current address list & redo lookup */
1554  port = _dbus_string_get_const_data(retport);
1555  freeaddrinfo(ai);
1556  goto redo_lookup_with_port;
1557  }
1558  else
1559  {
1560  if (!_dbus_string_append(retport, port))
1561  {
1563  goto failed;
1564  }
1565  }
1566  }
1567 
1568  tmp = tmp->ai_next;
1569  }
1570  freeaddrinfo(ai);
1571  ai = NULL;
1572 
1573  if (!nlisten_fd)
1574  {
1575  errno = EADDRINUSE;
1576  dbus_set_error (error, _dbus_error_from_errno (errno),
1577  "Failed to bind socket \"%s:%s\": %s",
1578  host ? host : "*", port, _dbus_strerror (errno));
1579  goto failed;
1580  }
1581 
1582  for (i = 0 ; i < nlisten_fd ; i++)
1583  {
1584  if (!_dbus_set_fd_nonblocking (listen_fd[i].fd, error))
1585  {
1586  goto failed;
1587  }
1588  }
1589 
1590  *fds_p = listen_fd;
1591 
1592  return nlisten_fd;
1593 
1594  failed:
1595  if (ai)
1596  freeaddrinfo(ai);
1597  for (i = 0 ; i < nlisten_fd ; i++)
1598  _dbus_close(listen_fd[i].fd, NULL);
1599  dbus_free(listen_fd);
1600  return -1;
1601 }
1602 
1603 static dbus_bool_t
1604 write_credentials_byte (int server_fd,
1605  DBusError *error)
1606 {
1607  int bytes_written;
1608  char buf[1] = { '\0' };
1609 #if defined(HAVE_CMSGCRED)
1610  union {
1611  struct cmsghdr hdr;
1612  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1613  } cmsg;
1614  struct iovec iov;
1615  struct msghdr msg;
1616  iov.iov_base = buf;
1617  iov.iov_len = 1;
1618 
1619  _DBUS_ZERO(msg);
1620  msg.msg_iov = &iov;
1621  msg.msg_iovlen = 1;
1622 
1623  msg.msg_control = (caddr_t) &cmsg;
1624  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1625  _DBUS_ZERO(cmsg);
1626  cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
1627  cmsg.hdr.cmsg_level = SOL_SOCKET;
1628  cmsg.hdr.cmsg_type = SCM_CREDS;
1629 #endif
1630 
1631  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1632 
1633  again:
1634 
1635 #if defined(HAVE_CMSGCRED)
1636  bytes_written = sendmsg (server_fd, &msg, 0
1637 #if HAVE_DECL_MSG_NOSIGNAL
1638  |MSG_NOSIGNAL
1639 #endif
1640  );
1641 
1642  /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg()
1643  * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD
1644  * only allows that on AF_UNIX. Try just doing a send() instead. */
1645  if (bytes_written < 0 && errno == EINVAL)
1646 #endif
1647  {
1648  bytes_written = send (server_fd, buf, 1, 0
1649 #if HAVE_DECL_MSG_NOSIGNAL
1650  |MSG_NOSIGNAL
1651 #endif
1652  );
1653  }
1654 
1655  if (bytes_written < 0 && errno == EINTR)
1656  goto again;
1657 
1658  if (bytes_written < 0)
1659  {
1660  dbus_set_error (error, _dbus_error_from_errno (errno),
1661  "Failed to write credentials byte: %s",
1662  _dbus_strerror (errno));
1663  return FALSE;
1664  }
1665  else if (bytes_written == 0)
1666  {
1668  "wrote zero bytes writing credentials byte");
1669  return FALSE;
1670  }
1671  else
1672  {
1673  _dbus_assert (bytes_written == 1);
1674  _dbus_verbose ("wrote credentials byte\n");
1675  return TRUE;
1676  }
1677 }
1678 
1679 /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */
1680 static dbus_bool_t
1681 add_linux_security_label_to_credentials (int client_fd,
1682  DBusCredentials *credentials)
1683 {
1684 #if defined(__linux__) && defined(SO_PEERSEC)
1685  DBusString buf;
1686  socklen_t len = 1024;
1687  dbus_bool_t oom = FALSE;
1688 
1689  if (!_dbus_string_init_preallocated (&buf, len) ||
1690  !_dbus_string_set_length (&buf, len))
1691  return FALSE;
1692 
1693  while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
1694  _dbus_string_get_data (&buf), &len) < 0)
1695  {
1696  int e = errno;
1697 
1698  _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
1699  _dbus_strerror (e), (unsigned long) len);
1700 
1701  if (e != ERANGE || len <= _dbus_string_get_length_uint (&buf))
1702  {
1703  _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
1704  _dbus_strerror (e));
1705  goto out;
1706  }
1707 
1708  /* If not enough space, len is updated to be enough.
1709  * Try again with a large enough buffer. */
1710  if (!_dbus_string_set_length (&buf, len))
1711  {
1712  oom = TRUE;
1713  goto out;
1714  }
1715 
1716  _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
1717  }
1718 
1719  if (len <= 0)
1720  {
1721  _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
1722  (unsigned long) len);
1723  goto out;
1724  }
1725 
1726  if (len > _dbus_string_get_length_uint (&buf))
1727  {
1728  _dbus_verbose ("%lu > %u", (unsigned long) len,
1729  _dbus_string_get_length_uint (&buf));
1730  _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
1731  }
1732 
1733  if (_dbus_string_get_byte (&buf, len - 1) == 0)
1734  {
1735  /* the kernel included the trailing \0 in its count,
1736  * but DBusString always has an extra \0 after the data anyway */
1737  _dbus_verbose ("subtracting trailing \\0\n");
1738  len--;
1739  }
1740 
1741  if (!_dbus_string_set_length (&buf, len))
1742  {
1743  _dbus_assert_not_reached ("shortening string should not lead to OOM");
1744  oom = TRUE;
1745  goto out;
1746  }
1747 
1748  if (strlen (_dbus_string_get_const_data (&buf)) != len)
1749  {
1750  /* LSM people on the linux-security-module@ mailing list say this
1751  * should never happen: the label should be a bytestring with
1752  * an optional trailing \0 */
1753  _dbus_verbose ("security label from kernel had an embedded \\0, "
1754  "ignoring it\n");
1755  goto out;
1756  }
1757 
1758  _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
1759  (unsigned long) len,
1760  _dbus_string_get_const_data (&buf));
1761 
1763  _dbus_string_get_const_data (&buf)))
1764  {
1765  oom = TRUE;
1766  goto out;
1767  }
1768 
1769 out:
1770  _dbus_string_free (&buf);
1771  return !oom;
1772 #else
1773  /* no error */
1774  return TRUE;
1775 #endif
1776 }
1777 
1820  DBusCredentials *credentials,
1821  DBusError *error)
1822 {
1823  struct msghdr msg;
1824  struct iovec iov;
1825  char buf;
1826  dbus_uid_t uid_read;
1827  dbus_pid_t pid_read;
1828  int bytes_read;
1829 
1830 #ifdef HAVE_CMSGCRED
1831  union {
1832  struct cmsghdr hdr;
1833  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
1834  } cmsg;
1835 #endif
1836 
1837  /* The POSIX spec certainly doesn't promise this, but
1838  * we need these assertions to fail as soon as we're wrong about
1839  * it so we can do the porting fixups
1840  */
1841  _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
1842  _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
1843  _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
1844 
1845  uid_read = DBUS_UID_UNSET;
1846  pid_read = DBUS_PID_UNSET;
1847 
1848  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1849 
1850  _dbus_credentials_clear (credentials);
1851 
1852  iov.iov_base = &buf;
1853  iov.iov_len = 1;
1854 
1855  _DBUS_ZERO(msg);
1856  msg.msg_iov = &iov;
1857  msg.msg_iovlen = 1;
1858 
1859 #if defined(HAVE_CMSGCRED)
1860  _DBUS_ZERO(cmsg);
1861  msg.msg_control = (caddr_t) &cmsg;
1862  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
1863 #endif
1864 
1865  again:
1866  bytes_read = recvmsg (client_fd.fd, &msg, 0);
1867 
1868  if (bytes_read < 0)
1869  {
1870  if (errno == EINTR)
1871  goto again;
1872 
1873  /* EAGAIN or EWOULDBLOCK would be unexpected here since we would
1874  * normally only call read_credentials if the socket was ready
1875  * for reading
1876  */
1877 
1878  dbus_set_error (error, _dbus_error_from_errno (errno),
1879  "Failed to read credentials byte: %s",
1880  _dbus_strerror (errno));
1881  return FALSE;
1882  }
1883  else if (bytes_read == 0)
1884  {
1885  /* this should not happen unless we are using recvmsg wrong,
1886  * so is essentially here for paranoia
1887  */
1889  "Failed to read credentials byte (zero-length read)");
1890  return FALSE;
1891  }
1892  else if (buf != '\0')
1893  {
1895  "Credentials byte was not nul");
1896  return FALSE;
1897  }
1898 
1899  _dbus_verbose ("read credentials byte\n");
1900 
1901  {
1902 #ifdef SO_PEERCRED
1903  /* Supported by at least Linux and OpenBSD, with minor differences.
1904  *
1905  * This mechanism passes the process ID through and does not require
1906  * the peer's cooperation, so we prefer it over all others. Notably,
1907  * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD
1908  * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all,
1909  * because this is much less fragile.
1910  */
1911 #ifdef __OpenBSD__
1912  struct sockpeercred cr;
1913 #else
1914  struct ucred cr;
1915 #endif
1916  int cr_len = sizeof (cr);
1917 
1918  if (getsockopt (client_fd.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0)
1919  {
1920  _dbus_verbose ("Failed to getsockopt(SO_PEERCRED): %s\n",
1921  _dbus_strerror (errno));
1922  }
1923  else if (cr_len != sizeof (cr))
1924  {
1925  _dbus_verbose ("Failed to getsockopt(SO_PEERCRED), returned %d bytes, expected %d\n",
1926  cr_len, (int) sizeof (cr));
1927  }
1928  else
1929  {
1930  pid_read = cr.pid;
1931  uid_read = cr.uid;
1932  }
1933 #elif defined(HAVE_UNPCBID) && defined(LOCAL_PEEREID)
1934  /* Another variant of the above - used on NetBSD
1935  */
1936  struct unpcbid cr;
1937  socklen_t cr_len = sizeof (cr);
1938 
1939  if (getsockopt (client_fd.fd, 0, LOCAL_PEEREID, &cr, &cr_len) != 0)
1940  {
1941  _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID): %s\n",
1942  _dbus_strerror (errno));
1943  }
1944  else if (cr_len != sizeof (cr))
1945  {
1946  _dbus_verbose ("Failed to getsockopt(LOCAL_PEEREID), returned %d bytes, expected %d\n",
1947  cr_len, (int) sizeof (cr));
1948  }
1949  else
1950  {
1951  pid_read = cr.unp_pid;
1952  uid_read = cr.unp_euid;
1953  }
1954 #elif defined(HAVE_CMSGCRED)
1955  /* We only check for HAVE_CMSGCRED, but we're really assuming that the
1956  * presence of that struct implies SCM_CREDS. Supported by at least
1957  * FreeBSD and DragonflyBSD.
1958  *
1959  * This mechanism requires the peer to help us (it has to send us a
1960  * SCM_CREDS message) but it does pass the process ID through,
1961  * which makes it better than getpeereid().
1962  */
1963  struct cmsgcred *cred;
1964  struct cmsghdr *cmsgp;
1965 
1966  for (cmsgp = CMSG_FIRSTHDR (&msg);
1967  cmsgp != NULL;
1968  cmsgp = CMSG_NXTHDR (&msg, cmsgp))
1969  {
1970  if (cmsgp->cmsg_type == SCM_CREDS &&
1971  cmsgp->cmsg_level == SOL_SOCKET &&
1972  cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
1973  {
1974  cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
1975  pid_read = cred->cmcred_pid;
1976  uid_read = cred->cmcred_euid;
1977  break;
1978  }
1979  }
1980 
1981 #elif defined(HAVE_GETPEERUCRED)
1982  /* Supported in at least Solaris >= 10. It should probably be higher
1983  * up this list, because it carries the pid and we use this code path
1984  * for audit data. */
1985  ucred_t * ucred = NULL;
1986  if (getpeerucred (client_fd.fd, &ucred) == 0)
1987  {
1988  pid_read = ucred_getpid (ucred);
1989  uid_read = ucred_geteuid (ucred);
1990 #ifdef HAVE_ADT
1991  /* generate audit session data based on socket ucred */
1992  adt_session_data_t *adth = NULL;
1993  adt_export_data_t *data = NULL;
1994  size_t size = 0;
1995  if (adt_start_session (&adth, NULL, 0) || (adth == NULL))
1996  {
1997  _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno));
1998  }
1999  else
2000  {
2001  if (adt_set_from_ucred (adth, ucred, ADT_NEW))
2002  {
2003  _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno));
2004  }
2005  else
2006  {
2007  size = adt_export_session_data (adth, &data);
2008  if (size <= 0)
2009  {
2010  _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno));
2011  }
2012  else
2013  {
2014  _dbus_credentials_add_adt_audit_data (credentials, data, size);
2015  free (data);
2016  }
2017  }
2018  (void) adt_end_session (adth);
2019  }
2020 #endif /* HAVE_ADT */
2021  }
2022  else
2023  {
2024  _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno));
2025  }
2026  if (ucred != NULL)
2027  ucred_free (ucred);
2028 
2029  /* ----------------------------------------------------------------
2030  * When adding new mechanisms, please add them above this point
2031  * if they support passing the process ID through, or below if not.
2032  * ---------------------------------------------------------------- */
2033 
2034 #elif defined(HAVE_GETPEEREID)
2035  /* getpeereid() originates from D.J. Bernstein and is fairly
2036  * widely-supported. According to a web search, it might be present in
2037  * any/all of:
2038  *
2039  * - AIX?
2040  * - Blackberry?
2041  * - Cygwin
2042  * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid)
2043  * - Mac OS X
2044  * - Minix 3.1.8+
2045  * - MirBSD?
2046  * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid)
2047  * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid)
2048  * - QNX?
2049  */
2050  uid_t euid;
2051  gid_t egid;
2052  if (getpeereid (client_fd.fd, &euid, &egid) == 0)
2053  {
2054  uid_read = euid;
2055  }
2056  else
2057  {
2058  _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno));
2059  }
2060 #else /* no supported mechanism */
2061 
2062 #warning Socket credentials not supported on this Unix OS
2063 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus
2064 
2065  /* Please add other operating systems known to support at least one of
2066  * the mechanisms above to this list, keeping alphabetical order.
2067  * Everything not in this list is best-effort.
2068  */
2069 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
2070  defined(__linux__) || \
2071  defined(__OpenBSD__) || \
2072  defined(__NetBSD__)
2073 # error Credentials passing not working on this OS is a regression!
2074 #endif
2075 
2076  _dbus_verbose ("Socket credentials not supported on this OS\n");
2077 #endif
2078  }
2079 
2080  _dbus_verbose ("Credentials:"
2081  " pid "DBUS_PID_FORMAT
2082  " uid "DBUS_UID_FORMAT
2083  "\n",
2084  pid_read,
2085  uid_read);
2086 
2087  if (pid_read != DBUS_PID_UNSET)
2088  {
2089  if (!_dbus_credentials_add_pid (credentials, pid_read))
2090  {
2091  _DBUS_SET_OOM (error);
2092  return FALSE;
2093  }
2094  }
2095 
2096  if (uid_read != DBUS_UID_UNSET)
2097  {
2098  if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
2099  {
2100  _DBUS_SET_OOM (error);
2101  return FALSE;
2102  }
2103  }
2104 
2105  if (!add_linux_security_label_to_credentials (client_fd.fd, credentials))
2106  {
2107  _DBUS_SET_OOM (error);
2108  return FALSE;
2109  }
2110 
2111  return TRUE;
2112 }
2113 
2133  DBusError *error)
2134 {
2135  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2136 
2137  if (write_credentials_byte (server_fd.fd, error))
2138  return TRUE;
2139  else
2140  return FALSE;
2141 }
2142 
2152 DBusSocket
2154 {
2155  DBusSocket client_fd;
2156  struct sockaddr addr;
2157  socklen_t addrlen;
2158 #ifdef HAVE_ACCEPT4
2159  dbus_bool_t cloexec_done;
2160 #endif
2161 
2162  addrlen = sizeof (addr);
2163 
2164  retry:
2165 
2166 #ifdef HAVE_ACCEPT4
2167  /*
2168  * At compile-time, we assume that if accept4() is available in
2169  * libc headers, SOCK_CLOEXEC is too. At runtime, it is still
2170  * not necessarily true that either is supported by the running kernel.
2171  */
2172  client_fd.fd = accept4 (listen_fd.fd, &addr, &addrlen, SOCK_CLOEXEC);
2173  cloexec_done = client_fd.fd >= 0;
2174 
2175  if (client_fd.fd < 0 && (errno == ENOSYS || errno == EINVAL))
2176 #endif
2177  {
2178  client_fd.fd = accept (listen_fd.fd, &addr, &addrlen);
2179  }
2180 
2181  if (client_fd.fd < 0)
2182  {
2183  if (errno == EINTR)
2184  goto retry;
2185  }
2186 
2187  _dbus_verbose ("client fd %d accepted\n", client_fd.fd);
2188 
2189 #ifdef HAVE_ACCEPT4
2190  if (!cloexec_done)
2191 #endif
2192  {
2193  _dbus_fd_set_close_on_exec(client_fd.fd);
2194  }
2195 
2196  return client_fd;
2197 }
2198 
2209 {
2210  const char *directory;
2211  struct stat sb;
2212 
2213  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2214 
2215  directory = _dbus_string_get_const_data (dir);
2216 
2217  if (stat (directory, &sb) < 0)
2218  {
2219  dbus_set_error (error, _dbus_error_from_errno (errno),
2220  "%s", _dbus_strerror (errno));
2221 
2222  return FALSE;
2223  }
2224 
2225  if (sb.st_uid != geteuid ())
2226  {
2228  "%s directory is owned by user %lu, not %lu",
2229  directory,
2230  (unsigned long) sb.st_uid,
2231  (unsigned long) geteuid ());
2232  return FALSE;
2233  }
2234 
2235  if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) ||
2236  (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode))
2237  {
2239  "%s directory is not private to the user", directory);
2240  return FALSE;
2241  }
2242 
2243  return TRUE;
2244 }
2245 
2246 static dbus_bool_t
2247 fill_user_info_from_passwd (struct passwd *p,
2248  DBusUserInfo *info,
2249  DBusError *error)
2250 {
2251  _dbus_assert (p->pw_name != NULL);
2252  _dbus_assert (p->pw_dir != NULL);
2253 
2254  info->uid = p->pw_uid;
2255  info->primary_gid = p->pw_gid;
2256  info->username = _dbus_strdup (p->pw_name);
2257  info->homedir = _dbus_strdup (p->pw_dir);
2258 
2259  if (info->username == NULL ||
2260  info->homedir == NULL)
2261  {
2263  return FALSE;
2264  }
2265 
2266  return TRUE;
2267 }
2268 
2269 static dbus_bool_t
2270 fill_user_info (DBusUserInfo *info,
2271  dbus_uid_t uid,
2272  const DBusString *username,
2273  DBusError *error)
2274 {
2275  const char *username_c;
2276 
2277  /* exactly one of username/uid provided */
2278  _dbus_assert (username != NULL || uid != DBUS_UID_UNSET);
2279  _dbus_assert (username == NULL || uid == DBUS_UID_UNSET);
2280 
2281  info->uid = DBUS_UID_UNSET;
2282  info->primary_gid = DBUS_GID_UNSET;
2283  info->group_ids = NULL;
2284  info->n_group_ids = 0;
2285  info->username = NULL;
2286  info->homedir = NULL;
2287 
2288  if (username != NULL)
2289  username_c = _dbus_string_get_const_data (username);
2290  else
2291  username_c = NULL;
2292 
2293  /* For now assuming that the getpwnam() and getpwuid() flavors
2294  * are always symmetrical, if not we have to add more configure
2295  * checks
2296  */
2297 
2298 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R)
2299  {
2300  struct passwd *p;
2301  int result;
2302  size_t buflen;
2303  char *buf;
2304  struct passwd p_str;
2305 
2306  /* retrieve maximum needed size for buf */
2307  buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
2308 
2309  /* sysconf actually returns a long, but everything else expects size_t,
2310  * so just recast here.
2311  * https://bugs.freedesktop.org/show_bug.cgi?id=17061
2312  */
2313  if ((long) buflen <= 0)
2314  buflen = 1024;
2315 
2316  result = -1;
2317  while (1)
2318  {
2319  buf = dbus_malloc (buflen);
2320  if (buf == NULL)
2321  {
2323  return FALSE;
2324  }
2325 
2326  p = NULL;
2327 #ifdef HAVE_POSIX_GETPWNAM_R
2328  if (uid != DBUS_UID_UNSET)
2329  result = getpwuid_r (uid, &p_str, buf, buflen,
2330  &p);
2331  else
2332  result = getpwnam_r (username_c, &p_str, buf, buflen,
2333  &p);
2334 #else
2335  if (uid != DBUS_UID_UNSET)
2336  p = getpwuid_r (uid, &p_str, buf, buflen);
2337  else
2338  p = getpwnam_r (username_c, &p_str, buf, buflen);
2339  result = 0;
2340 #endif /* !HAVE_POSIX_GETPWNAM_R */
2341  //Try a bigger buffer if ERANGE was returned
2342  if (result == ERANGE && buflen < 512 * 1024)
2343  {
2344  dbus_free (buf);
2345  buflen *= 2;
2346  }
2347  else
2348  {
2349  break;
2350  }
2351  }
2352  if (result == 0 && p == &p_str)
2353  {
2354  if (!fill_user_info_from_passwd (p, info, error))
2355  {
2356  dbus_free (buf);
2357  return FALSE;
2358  }
2359  dbus_free (buf);
2360  }
2361  else
2362  {
2363  dbus_set_error (error, _dbus_error_from_errno (errno),
2364  "User \"%s\" unknown or no memory to allocate password entry\n",
2365  username_c ? username_c : "???");
2366  _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2367  dbus_free (buf);
2368  return FALSE;
2369  }
2370  }
2371 #else /* ! HAVE_GETPWNAM_R */
2372  {
2373  /* I guess we're screwed on thread safety here */
2374  struct passwd *p;
2375 
2376  if (uid != DBUS_UID_UNSET)
2377  p = getpwuid (uid);
2378  else
2379  p = getpwnam (username_c);
2380 
2381  if (p != NULL)
2382  {
2383  if (!fill_user_info_from_passwd (p, info, error))
2384  {
2385  return FALSE;
2386  }
2387  }
2388  else
2389  {
2390  dbus_set_error (error, _dbus_error_from_errno (errno),
2391  "User \"%s\" unknown or no memory to allocate password entry\n",
2392  username_c ? username_c : "???");
2393  _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???");
2394  return FALSE;
2395  }
2396  }
2397 #endif /* ! HAVE_GETPWNAM_R */
2398 
2399  /* Fill this in so we can use it to get groups */
2400  username_c = info->username;
2401 
2402 #ifdef HAVE_GETGROUPLIST
2403  {
2404  gid_t *buf;
2405  int buf_count;
2406  int i;
2407  int initial_buf_count;
2408 
2409  initial_buf_count = 17;
2410  buf_count = initial_buf_count;
2411  buf = dbus_new (gid_t, buf_count);
2412  if (buf == NULL)
2413  {
2415  goto failed;
2416  }
2417 
2418  if (getgrouplist (username_c,
2419  info->primary_gid,
2420  buf, &buf_count) < 0)
2421  {
2422  gid_t *new;
2423  /* Presumed cause of negative return code: buf has insufficient
2424  entries to hold the entire group list. The Linux behavior in this
2425  case is to pass back the actual number of groups in buf_count, but
2426  on Mac OS X 10.5, buf_count is unhelpfully left alone.
2427  So as a hack, try to help out a bit by guessing a larger
2428  number of groups, within reason.. might still fail, of course,
2429  but we can at least print a more informative message. I looked up
2430  the "right way" to do this by downloading Apple's own source code
2431  for the "id" command, and it turns out that they use an
2432  undocumented library function getgrouplist_2 (!) which is not
2433  declared in any header in /usr/include (!!). That did not seem
2434  like the way to go here.
2435  */
2436  if (buf_count == initial_buf_count)
2437  {
2438  buf_count *= 16; /* Retry with an arbitrarily scaled-up array */
2439  }
2440  new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
2441  if (new == NULL)
2442  {
2444  dbus_free (buf);
2445  goto failed;
2446  }
2447 
2448  buf = new;
2449 
2450  errno = 0;
2451  if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0)
2452  {
2453  if (errno == 0)
2454  {
2455  _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.",
2456  username_c, buf_count, buf_count);
2457  }
2458  else
2459  {
2460  dbus_set_error (error,
2461  _dbus_error_from_errno (errno),
2462  "Failed to get groups for username \"%s\" primary GID "
2463  DBUS_GID_FORMAT ": %s\n",
2464  username_c, info->primary_gid,
2465  _dbus_strerror (errno));
2466  dbus_free (buf);
2467  goto failed;
2468  }
2469  }
2470  }
2471 
2472  info->group_ids = dbus_new (dbus_gid_t, buf_count);
2473  if (info->group_ids == NULL)
2474  {
2476  dbus_free (buf);
2477  goto failed;
2478  }
2479 
2480  for (i = 0; i < buf_count; ++i)
2481  info->group_ids[i] = buf[i];
2482 
2483  info->n_group_ids = buf_count;
2484 
2485  dbus_free (buf);
2486  }
2487 #else /* HAVE_GETGROUPLIST */
2488  {
2489  /* We just get the one group ID */
2490  info->group_ids = dbus_new (dbus_gid_t, 1);
2491  if (info->group_ids == NULL)
2492  {
2494  goto failed;
2495  }
2496 
2497  info->n_group_ids = 1;
2498 
2499  (info->group_ids)[0] = info->primary_gid;
2500  }
2501 #endif /* HAVE_GETGROUPLIST */
2502 
2503  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2504 
2505  return TRUE;
2506 
2507  failed:
2508  _DBUS_ASSERT_ERROR_IS_SET (error);
2509  return FALSE;
2510 }
2511 
2522  const DBusString *username,
2523  DBusError *error)
2524 {
2525  return fill_user_info (info, DBUS_UID_UNSET,
2526  username, error);
2527 }
2528 
2539  dbus_uid_t uid,
2540  DBusError *error)
2541 {
2542  return fill_user_info (info, uid,
2543  NULL, error);
2544 }
2545 
2555 {
2556  /* The POSIX spec certainly doesn't promise this, but
2557  * we need these assertions to fail as soon as we're wrong about
2558  * it so we can do the porting fixups
2559  */
2560  _DBUS_STATIC_ASSERT (sizeof (pid_t) <= sizeof (dbus_pid_t));
2561  _DBUS_STATIC_ASSERT (sizeof (uid_t) <= sizeof (dbus_uid_t));
2562  _DBUS_STATIC_ASSERT (sizeof (gid_t) <= sizeof (dbus_gid_t));
2563 
2564  if (!_dbus_credentials_add_pid(credentials, _dbus_getpid()))
2565  return FALSE;
2566  if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid()))
2567  return FALSE;
2568 
2569  return TRUE;
2570 }
2571 
2585 {
2586  return _dbus_string_append_uint (str,
2587  _dbus_geteuid ());
2588 }
2589 
2594 dbus_pid_t
2596 {
2597  return getpid ();
2598 }
2599 
2603 dbus_uid_t
2605 {
2606  return getuid ();
2607 }
2608 
2612 dbus_uid_t
2614 {
2615  return geteuid ();
2616 }
2617 
2624 unsigned long
2626 {
2627  return getpid ();
2628 }
2629 
2638 _dbus_parse_uid (const DBusString *uid_str,
2639  dbus_uid_t *uid)
2640 {
2641  int end;
2642  long val;
2643 
2644  if (_dbus_string_get_length (uid_str) == 0)
2645  {
2646  _dbus_verbose ("UID string was zero length\n");
2647  return FALSE;
2648  }
2649 
2650  val = -1;
2651  end = 0;
2652  if (!_dbus_string_parse_int (uid_str, 0, &val,
2653  &end))
2654  {
2655  _dbus_verbose ("could not parse string as a UID\n");
2656  return FALSE;
2657  }
2658 
2659  if (end != _dbus_string_get_length (uid_str))
2660  {
2661  _dbus_verbose ("string contained trailing stuff after UID\n");
2662  return FALSE;
2663  }
2664 
2665  *uid = val;
2666 
2667  return TRUE;
2668 }
2669 
2670 #if !DBUS_USE_SYNC
2671 /* To be thread-safe by default on platforms that don't necessarily have
2672  * atomic operations (notably Debian armel, which is armv4t), we must
2673  * use a mutex that can be initialized statically, like this.
2674  * GLib >= 2.32 uses a similar system.
2675  */
2676 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
2677 #endif
2678 
2685 dbus_int32_t
2687 {
2688 #if DBUS_USE_SYNC
2689  return __sync_add_and_fetch(&atomic->value, 1)-1;
2690 #else
2691  dbus_int32_t res;
2692 
2693  pthread_mutex_lock (&atomic_mutex);
2694  res = atomic->value;
2695  atomic->value += 1;
2696  pthread_mutex_unlock (&atomic_mutex);
2697 
2698  return res;
2699 #endif
2700 }
2701 
2708 dbus_int32_t
2710 {
2711 #if DBUS_USE_SYNC
2712  return __sync_sub_and_fetch(&atomic->value, 1)+1;
2713 #else
2714  dbus_int32_t res;
2715 
2716  pthread_mutex_lock (&atomic_mutex);
2717  res = atomic->value;
2718  atomic->value -= 1;
2719  pthread_mutex_unlock (&atomic_mutex);
2720 
2721  return res;
2722 #endif
2723 }
2724 
2732 dbus_int32_t
2734 {
2735 #if DBUS_USE_SYNC
2736  __sync_synchronize ();
2737  return atomic->value;
2738 #else
2739  dbus_int32_t res;
2740 
2741  pthread_mutex_lock (&atomic_mutex);
2742  res = atomic->value;
2743  pthread_mutex_unlock (&atomic_mutex);
2744 
2745  return res;
2746 #endif
2747 }
2748 
2757 int
2759  int n_fds,
2760  int timeout_milliseconds)
2761 {
2762 #if defined(HAVE_POLL) && !defined(BROKEN_POLL)
2763  /* DBusPollFD is a struct pollfd in this code path, so we can just poll() */
2764  if (timeout_milliseconds < -1)
2765  {
2766  timeout_milliseconds = -1;
2767  }
2768 
2769  return poll (fds,
2770  n_fds,
2771  timeout_milliseconds);
2772 #else /* ! HAVE_POLL */
2773  /* Emulate poll() in terms of select() */
2774  fd_set read_set, write_set, err_set;
2775  int max_fd = 0;
2776  int i;
2777  struct timeval tv;
2778  int ready;
2779 
2780  FD_ZERO (&read_set);
2781  FD_ZERO (&write_set);
2782  FD_ZERO (&err_set);
2783 
2784  for (i = 0; i < n_fds; i++)
2785  {
2786  DBusPollFD *fdp = &fds[i];
2787 
2788  if (fdp->events & _DBUS_POLLIN)
2789  FD_SET (fdp->fd, &read_set);
2790 
2791  if (fdp->events & _DBUS_POLLOUT)
2792  FD_SET (fdp->fd, &write_set);
2793 
2794  FD_SET (fdp->fd, &err_set);
2795 
2796  max_fd = MAX (max_fd, fdp->fd);
2797  }
2798 
2799  tv.tv_sec = timeout_milliseconds / 1000;
2800  tv.tv_usec = (timeout_milliseconds % 1000) * 1000;
2801 
2802  ready = select (max_fd + 1, &read_set, &write_set, &err_set,
2803  timeout_milliseconds < 0 ? NULL : &tv);
2804 
2805  if (ready > 0)
2806  {
2807  for (i = 0; i < n_fds; i++)
2808  {
2809  DBusPollFD *fdp = &fds[i];
2810 
2811  fdp->revents = 0;
2812 
2813  if (FD_ISSET (fdp->fd, &read_set))
2814  fdp->revents |= _DBUS_POLLIN;
2815 
2816  if (FD_ISSET (fdp->fd, &write_set))
2817  fdp->revents |= _DBUS_POLLOUT;
2818 
2819  if (FD_ISSET (fdp->fd, &err_set))
2820  fdp->revents |= _DBUS_POLLERR;
2821  }
2822  }
2823 
2824  return ready;
2825 #endif
2826 }
2827 
2835 void
2837  long *tv_usec)
2838 {
2839 #ifdef HAVE_MONOTONIC_CLOCK
2840  struct timespec ts;
2841  clock_gettime (CLOCK_MONOTONIC, &ts);
2842 
2843  if (tv_sec)
2844  *tv_sec = ts.tv_sec;
2845  if (tv_usec)
2846  *tv_usec = ts.tv_nsec / 1000;
2847 #else
2848  struct timeval t;
2849 
2850  gettimeofday (&t, NULL);
2851 
2852  if (tv_sec)
2853  *tv_sec = t.tv_sec;
2854  if (tv_usec)
2855  *tv_usec = t.tv_usec;
2856 #endif
2857 }
2858 
2866 void
2867 _dbus_get_real_time (long *tv_sec,
2868  long *tv_usec)
2869 {
2870  struct timeval t;
2871 
2872  gettimeofday (&t, NULL);
2873 
2874  if (tv_sec)
2875  *tv_sec = t.tv_sec;
2876  if (tv_usec)
2877  *tv_usec = t.tv_usec;
2878 }
2879 
2890  DBusError *error)
2891 {
2892  const char *filename_c;
2893 
2894  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2895 
2896  filename_c = _dbus_string_get_const_data (filename);
2897 
2898  if (mkdir (filename_c, 0700) < 0)
2899  {
2900  if (errno == EEXIST)
2901  return TRUE;
2902 
2904  "Failed to create directory %s: %s\n",
2905  filename_c, _dbus_strerror (errno));
2906  return FALSE;
2907  }
2908  else
2909  return TRUE;
2910 }
2911 
2924  const DBusString *next_component)
2925 {
2926  dbus_bool_t dir_ends_in_slash;
2927  dbus_bool_t file_starts_with_slash;
2928 
2929  if (_dbus_string_get_length (dir) == 0 ||
2930  _dbus_string_get_length (next_component) == 0)
2931  return TRUE;
2932 
2933  dir_ends_in_slash = '/' == _dbus_string_get_byte (dir,
2934  _dbus_string_get_length (dir) - 1);
2935 
2936  file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0);
2937 
2938  if (dir_ends_in_slash && file_starts_with_slash)
2939  {
2940  _dbus_string_shorten (dir, 1);
2941  }
2942  else if (!(dir_ends_in_slash || file_starts_with_slash))
2943  {
2944  if (!_dbus_string_append_byte (dir, '/'))
2945  return FALSE;
2946  }
2947 
2948  return _dbus_string_copy (next_component, 0, dir,
2949  _dbus_string_get_length (dir));
2950 }
2951 
2953 #define NANOSECONDS_PER_SECOND 1000000000
2954 
2955 #define MICROSECONDS_PER_SECOND 1000000
2956 
2957 #define MILLISECONDS_PER_SECOND 1000
2958 
2959 #define NANOSECONDS_PER_MILLISECOND 1000000
2960 
2961 #define MICROSECONDS_PER_MILLISECOND 1000
2962 
2967 void
2968 _dbus_sleep_milliseconds (int milliseconds)
2969 {
2970 #ifdef HAVE_NANOSLEEP
2971  struct timespec req;
2972  struct timespec rem;
2973 
2974  req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND;
2975  req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND;
2976  rem.tv_sec = 0;
2977  rem.tv_nsec = 0;
2978 
2979  while (nanosleep (&req, &rem) < 0 && errno == EINTR)
2980  req = rem;
2981 #elif defined (HAVE_USLEEP)
2982  usleep (milliseconds * MICROSECONDS_PER_MILLISECOND);
2983 #else /* ! HAVE_USLEEP */
2984  sleep (MAX (milliseconds / 1000, 1));
2985 #endif
2986 }
2987 
2999  int n_bytes,
3000  DBusError *error)
3001 {
3002  int old_len;
3003  int fd;
3004  int result;
3005 
3006  old_len = _dbus_string_get_length (str);
3007  fd = -1;
3008 
3009  /* note, urandom on linux will fall back to pseudorandom */
3010  fd = open ("/dev/urandom", O_RDONLY);
3011 
3012  if (fd < 0)
3013  {
3014  dbus_set_error (error, _dbus_error_from_errno (errno),
3015  "Could not open /dev/urandom: %s",
3016  _dbus_strerror (errno));
3017  return FALSE;
3018  }
3019 
3020  _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
3021 
3022  result = _dbus_read (fd, str, n_bytes);
3023 
3024  if (result != n_bytes)
3025  {
3026  if (result < 0)
3027  dbus_set_error (error, _dbus_error_from_errno (errno),
3028  "Could not read /dev/urandom: %s",
3029  _dbus_strerror (errno));
3030  else
3032  "Short read from /dev/urandom");
3033 
3034  _dbus_close (fd, NULL);
3035  _dbus_string_set_length (str, old_len);
3036  return FALSE;
3037  }
3038 
3039  _dbus_verbose ("Read %d bytes from /dev/urandom\n",
3040  n_bytes);
3041 
3042  _dbus_close (fd, NULL);
3043 
3044  return TRUE;
3045 }
3046 
3052 void
3053 _dbus_exit (int code)
3054 {
3055  _exit (code);
3056 }
3057 
3066 const char*
3067 _dbus_strerror (int error_number)
3068 {
3069  const char *msg;
3070 
3071  msg = strerror (error_number);
3072  if (msg == NULL)
3073  msg = "unknown";
3074 
3075  return msg;
3076 }
3077 
3081 void
3083 {
3084  signal (SIGPIPE, SIG_IGN);
3085 }
3086 
3094 void
3096 {
3097  int val;
3098 
3099  val = fcntl (fd, F_GETFD, 0);
3100 
3101  if (val < 0)
3102  return;
3103 
3104  val |= FD_CLOEXEC;
3105 
3106  fcntl (fd, F_SETFD, val);
3107 }
3108 
3117 _dbus_close (int fd,
3118  DBusError *error)
3119 {
3120  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3121 
3122  again:
3123  if (close (fd) < 0)
3124  {
3125  if (errno == EINTR)
3126  goto again;
3127 
3128  dbus_set_error (error, _dbus_error_from_errno (errno),
3129  "Could not close fd %d", fd);
3130  return FALSE;
3131  }
3132 
3133  return TRUE;
3134 }
3135 
3144 int
3145 _dbus_dup(int fd,
3146  DBusError *error)
3147 {
3148  int new_fd;
3149 
3150 #ifdef F_DUPFD_CLOEXEC
3151  dbus_bool_t cloexec_done;
3152 
3153  new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
3154  cloexec_done = new_fd >= 0;
3155 
3156  if (new_fd < 0 && errno == EINVAL)
3157 #endif
3158  {
3159  new_fd = fcntl(fd, F_DUPFD, 3);
3160  }
3161 
3162  if (new_fd < 0) {
3163 
3164  dbus_set_error (error, _dbus_error_from_errno (errno),
3165  "Could not duplicate fd %d", fd);
3166  return -1;
3167  }
3168 
3169 #ifdef F_DUPFD_CLOEXEC
3170  if (!cloexec_done)
3171 #endif
3172  {
3174  }
3175 
3176  return new_fd;
3177 }
3178 
3188  DBusError *error)
3189 {
3190  return _dbus_set_fd_nonblocking (fd.fd, error);
3191 }
3192 
3193 static dbus_bool_t
3194 _dbus_set_fd_nonblocking (int fd,
3195  DBusError *error)
3196 {
3197  int val;
3198 
3199  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3200 
3201  val = fcntl (fd, F_GETFL, 0);
3202  if (val < 0)
3203  {
3204  dbus_set_error (error, _dbus_error_from_errno (errno),
3205  "Failed to get flags from file descriptor %d: %s",
3206  fd, _dbus_strerror (errno));
3207  _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd,
3208  _dbus_strerror (errno));
3209  return FALSE;
3210  }
3211 
3212  if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0)
3213  {
3214  dbus_set_error (error, _dbus_error_from_errno (errno),
3215  "Failed to set nonblocking flag of file descriptor %d: %s",
3216  fd, _dbus_strerror (errno));
3217  _dbus_verbose ("Failed to set fd %d nonblocking: %s\n",
3218  fd, _dbus_strerror (errno));
3219 
3220  return FALSE;
3221  }
3222 
3223  return TRUE;
3224 }
3225 
3231 void
3233 {
3234 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC)
3235  void *bt[500];
3236  int bt_size;
3237  int i;
3238  char **syms;
3239 
3240  bt_size = backtrace (bt, 500);
3241 
3242  syms = backtrace_symbols (bt, bt_size);
3243 
3244  i = 0;
3245  while (i < bt_size)
3246  {
3247  /* don't use dbus_warn since it can _dbus_abort() */
3248  fprintf (stderr, " %s\n", syms[i]);
3249  ++i;
3250  }
3251  fflush (stderr);
3252 
3253  free (syms);
3254 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC)
3255  fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n");
3256 #else
3257  fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n");
3258 #endif
3259 }
3260 
3275  DBusSocket *fd2,
3276  dbus_bool_t blocking,
3277  DBusError *error)
3278 {
3279 #ifdef HAVE_SOCKETPAIR
3280  int fds[2];
3281  int retval;
3282 
3283 #ifdef SOCK_CLOEXEC
3284  dbus_bool_t cloexec_done;
3285 
3286  retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
3287  cloexec_done = retval >= 0;
3288 
3289  if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE))
3290 #endif
3291  {
3292  retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3293  }
3294 
3295  if (retval < 0)
3296  {
3297  dbus_set_error (error, _dbus_error_from_errno (errno),
3298  "Could not create full-duplex pipe");
3299  return FALSE;
3300  }
3301 
3302  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3303 
3304 #ifdef SOCK_CLOEXEC
3305  if (!cloexec_done)
3306 #endif
3307  {
3308  _dbus_fd_set_close_on_exec (fds[0]);
3309  _dbus_fd_set_close_on_exec (fds[1]);
3310  }
3311 
3312  if (!blocking &&
3313  (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
3314  !_dbus_set_fd_nonblocking (fds[1], NULL)))
3315  {
3316  dbus_set_error (error, _dbus_error_from_errno (errno),
3317  "Could not set full-duplex pipe nonblocking");
3318 
3319  _dbus_close (fds[0], NULL);
3320  _dbus_close (fds[1], NULL);
3321 
3322  return FALSE;
3323  }
3324 
3325  fd1->fd = fds[0];
3326  fd2->fd = fds[1];
3327 
3328  _dbus_verbose ("full-duplex pipe %d <-> %d\n",
3329  fd1->fd, fd2->fd);
3330 
3331  return TRUE;
3332 #else
3333  _dbus_warn ("_dbus_socketpair() not implemented on this OS\n");
3335  "_dbus_socketpair() not implemented on this OS");
3336  return FALSE;
3337 #endif
3338 }
3339 
3348 int
3350  va_list args)
3351 {
3352  char static_buf[1024];
3353  int bufsize = sizeof (static_buf);
3354  int len;
3355  va_list args_copy;
3356 
3357  DBUS_VA_COPY (args_copy, args);
3358  len = vsnprintf (static_buf, bufsize, format, args_copy);
3359  va_end (args_copy);
3360 
3361  /* If vsnprintf() returned non-negative, then either the string fits in
3362  * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf
3363  * returns the number of characters that were needed, or this OS returns the
3364  * truncated length.
3365  *
3366  * We ignore the possibility that snprintf might just ignore the length and
3367  * overrun the buffer (64-bit Solaris 7), because that's pathological.
3368  * If your libc is really that bad, come back when you have a better one. */
3369  if (len == bufsize)
3370  {
3371  /* This could be the truncated length (Tru64 and IRIX have this bug),
3372  * or the real length could be coincidentally the same. Which is it?
3373  * If vsnprintf returns the truncated length, we'll go to the slow
3374  * path. */
3375  DBUS_VA_COPY (args_copy, args);
3376 
3377  if (vsnprintf (static_buf, 1, format, args_copy) == 1)
3378  len = -1;
3379 
3380  va_end (args_copy);
3381  }
3382 
3383  /* If vsnprintf() returned negative, we have to do more work.
3384  * HP-UX returns negative. */
3385  while (len < 0)
3386  {
3387  char *buf;
3388 
3389  bufsize *= 2;
3390 
3391  buf = dbus_malloc (bufsize);
3392 
3393  if (buf == NULL)
3394  return -1;
3395 
3396  DBUS_VA_COPY (args_copy, args);
3397  len = vsnprintf (buf, bufsize, format, args_copy);
3398  va_end (args_copy);
3399 
3400  dbus_free (buf);
3401 
3402  /* If the reported length is exactly the buffer size, round up to the
3403  * next size, in case vsnprintf has been returning the truncated
3404  * length */
3405  if (len == bufsize)
3406  len = -1;
3407  }
3408 
3409  return len;
3410 }
3411 
3418 const char*
3420 {
3421  /* Protected by _DBUS_LOCK_sysdeps */
3422  static const char* tmpdir = NULL;
3423 
3424  if (!_DBUS_LOCK (sysdeps))
3425  return NULL;
3426 
3427  if (tmpdir == NULL)
3428  {
3429  /* TMPDIR is what glibc uses, then
3430  * glibc falls back to the P_tmpdir macro which
3431  * just expands to "/tmp"
3432  */
3433  if (tmpdir == NULL)
3434  tmpdir = getenv("TMPDIR");
3435 
3436  /* These two env variables are probably
3437  * broken, but maybe some OS uses them?
3438  */
3439  if (tmpdir == NULL)
3440  tmpdir = getenv("TMP");
3441  if (tmpdir == NULL)
3442  tmpdir = getenv("TEMP");
3443 
3444  /* And this is the sane fallback. */
3445  if (tmpdir == NULL)
3446  tmpdir = "/tmp";
3447  }
3448 
3449  _DBUS_UNLOCK (sysdeps);
3450 
3451  _dbus_assert(tmpdir != NULL);
3452 
3453  return tmpdir;
3454 }
3455 
3456 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD)
3457 
3476 static dbus_bool_t
3477 _read_subprocess_line_argv (const char *progpath,
3478  dbus_bool_t path_fallback,
3479  char * const *argv,
3480  DBusString *result,
3481  DBusError *error)
3482 {
3483  int result_pipe[2] = { -1, -1 };
3484  int errors_pipe[2] = { -1, -1 };
3485  pid_t pid;
3486  int ret;
3487  int status;
3488  int orig_len;
3489 
3490  dbus_bool_t retval;
3491  sigset_t new_set, old_set;
3492 
3493  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3494  retval = FALSE;
3495 
3496  /* We need to block any existing handlers for SIGCHLD temporarily; they
3497  * will cause waitpid() below to fail.
3498  * https://bugs.freedesktop.org/show_bug.cgi?id=21347
3499  */
3500  sigemptyset (&new_set);
3501  sigaddset (&new_set, SIGCHLD);
3502  sigprocmask (SIG_BLOCK, &new_set, &old_set);
3503 
3504  orig_len = _dbus_string_get_length (result);
3505 
3506 #define READ_END 0
3507 #define WRITE_END 1
3508  if (pipe (result_pipe) < 0)
3509  {
3510  dbus_set_error (error, _dbus_error_from_errno (errno),
3511  "Failed to create a pipe to call %s: %s",
3512  progpath, _dbus_strerror (errno));
3513  _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3514  progpath, _dbus_strerror (errno));
3515  goto out;
3516  }
3517  if (pipe (errors_pipe) < 0)
3518  {
3519  dbus_set_error (error, _dbus_error_from_errno (errno),
3520  "Failed to create a pipe to call %s: %s",
3521  progpath, _dbus_strerror (errno));
3522  _dbus_verbose ("Failed to create a pipe to call %s: %s\n",
3523  progpath, _dbus_strerror (errno));
3524  goto out;
3525  }
3526 
3527  pid = fork ();
3528  if (pid < 0)
3529  {
3530  dbus_set_error (error, _dbus_error_from_errno (errno),
3531  "Failed to fork() to call %s: %s",
3532  progpath, _dbus_strerror (errno));
3533  _dbus_verbose ("Failed to fork() to call %s: %s\n",
3534  progpath, _dbus_strerror (errno));
3535  goto out;
3536  }
3537 
3538  if (pid == 0)
3539  {
3540  /* child process */
3541  int fd;
3542 
3543  fd = open ("/dev/null", O_RDWR);
3544  if (fd == -1)
3545  /* huh?! can't open /dev/null? */
3546  _exit (1);
3547 
3548  _dbus_verbose ("/dev/null fd %d opened\n", fd);
3549 
3550  /* set-up stdXXX */
3551  close (result_pipe[READ_END]);
3552  close (errors_pipe[READ_END]);
3553 
3554  if (dup2 (fd, 0) == -1) /* setup stdin */
3555  _exit (1);
3556  if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */
3557  _exit (1);
3558  if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */
3559  _exit (1);
3560 
3561  _dbus_close_all ();
3562 
3563  sigprocmask (SIG_SETMASK, &old_set, NULL);
3564 
3565  /* If it looks fully-qualified, try execv first */
3566  if (progpath[0] == '/')
3567  {
3568  execv (progpath, argv);
3569  /* Ok, that failed. Now if path_fallback is given, let's
3570  * try unqualified. This is mostly a hack to work
3571  * around systems which ship dbus-launch in /usr/bin
3572  * but everything else in /bin (because dbus-launch
3573  * depends on X11).
3574  */
3575  if (path_fallback)
3576  /* We must have a slash, because we checked above */
3577  execvp (strrchr (progpath, '/')+1, argv);
3578  }
3579  else
3580  execvp (progpath, argv);
3581 
3582  /* still nothing, we failed */
3583  _exit (1);
3584  }
3585 
3586  /* parent process */
3587  close (result_pipe[WRITE_END]);
3588  close (errors_pipe[WRITE_END]);
3589  result_pipe[WRITE_END] = -1;
3590  errors_pipe[WRITE_END] = -1;
3591 
3592  ret = 0;
3593  do
3594  {
3595  ret = _dbus_read (result_pipe[READ_END], result, 1024);
3596  }
3597  while (ret > 0);
3598 
3599  /* reap the child process to avoid it lingering as zombie */
3600  do
3601  {
3602  ret = waitpid (pid, &status, 0);
3603  }
3604  while (ret == -1 && errno == EINTR);
3605 
3606  /* We succeeded if the process exited with status 0 and
3607  anything was read */
3608  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 )
3609  {
3610  /* The process ended with error */
3611  DBusString error_message;
3612  if (!_dbus_string_init (&error_message))
3613  {
3614  _DBUS_SET_OOM (error);
3615  goto out;
3616  }
3617 
3618  ret = 0;
3619  do
3620  {
3621  ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024);
3622  }
3623  while (ret > 0);
3624 
3625  _dbus_string_set_length (result, orig_len);
3626  if (_dbus_string_get_length (&error_message) > 0)
3628  "%s terminated abnormally with the following error: %s",
3629  progpath, _dbus_string_get_data (&error_message));
3630  else
3632  "%s terminated abnormally without any error message",
3633  progpath);
3634  goto out;
3635  }
3636 
3637  retval = TRUE;
3638 
3639  out:
3640  sigprocmask (SIG_SETMASK, &old_set, NULL);
3641 
3642  if (retval)
3643  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3644  else
3645  _DBUS_ASSERT_ERROR_IS_SET (error);
3646 
3647  if (result_pipe[0] != -1)
3648  close (result_pipe[0]);
3649  if (result_pipe[1] != -1)
3650  close (result_pipe[1]);
3651  if (errors_pipe[0] != -1)
3652  close (errors_pipe[0]);
3653  if (errors_pipe[1] != -1)
3654  close (errors_pipe[1]);
3655 
3656  return retval;
3657 }
3658 #endif
3659 
3673 _dbus_get_autolaunch_address (const char *scope,
3674  DBusString *address,
3675  DBusError *error)
3676 {
3677 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH
3678  /* Perform X11-based autolaunch. (We also support launchd-based autolaunch,
3679  * but that's done elsewhere, and if it worked, this function wouldn't
3680  * be called.) */
3681  const char *display;
3682  char *progpath;
3683  char *argv[6];
3684  int i;
3685  DBusString uuid;
3686  dbus_bool_t retval;
3687 
3688  if (_dbus_check_setuid ())
3689  {
3691  "Unable to autolaunch when setuid");
3692  return FALSE;
3693  }
3694 
3695  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3696  retval = FALSE;
3697 
3698  /* fd.o #19997: if $DISPLAY isn't set to something useful, then
3699  * dbus-launch-x11 is just going to fail. Rather than trying to
3700  * run it, we might as well bail out early with a nice error.
3701  *
3702  * This is not strictly true in a world where the user bus exists,
3703  * because dbus-launch --autolaunch knows how to connect to that -
3704  * but if we were going to connect to the user bus, we'd have done
3705  * so before trying autolaunch: in any case. */
3706  display = _dbus_getenv ("DISPLAY");
3707 
3708  if (display == NULL || display[0] == '\0')
3709  {
3711  "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11");
3712  return FALSE;
3713  }
3714 
3715  if (!_dbus_string_init (&uuid))
3716  {
3717  _DBUS_SET_OOM (error);
3718  return FALSE;
3719  }
3720 
3721  if (!_dbus_get_local_machine_uuid_encoded (&uuid, error))
3722  {
3723  goto out;
3724  }
3725 
3726 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
3727  if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL)
3728  progpath = TEST_BUS_LAUNCH_BINARY;
3729  else
3730 #endif
3731  progpath = DBUS_BINDIR "/dbus-launch";
3732  /*
3733  * argv[0] is always dbus-launch, that's the name what we'll
3734  * get from /proc, or ps(1), regardless what the progpath is,
3735  * see fd.o#69716
3736  */
3737  i = 0;
3738  argv[i] = "dbus-launch";
3739  ++i;
3740  argv[i] = "--autolaunch";
3741  ++i;
3742  argv[i] = _dbus_string_get_data (&uuid);
3743  ++i;
3744  argv[i] = "--binary-syntax";
3745  ++i;
3746  argv[i] = "--close-stderr";
3747  ++i;
3748  argv[i] = NULL;
3749  ++i;
3750 
3751  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3752 
3753  retval = _read_subprocess_line_argv (progpath,
3754  TRUE,
3755  argv, address, error);
3756 
3757  out:
3758  _dbus_string_free (&uuid);
3759  return retval;
3760 #else
3762  "Using X11 for dbus-daemon autolaunch was disabled at compile time, "
3763  "set your DBUS_SESSION_BUS_ADDRESS instead");
3764  return FALSE;
3765 #endif
3766 }
3767 
3788  dbus_bool_t create_if_not_found,
3789  DBusError *error)
3790 {
3791  DBusString filename;
3792  dbus_bool_t b;
3793 
3794  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3795 
3796  b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3797  if (b)
3798  return TRUE;
3799 
3800  dbus_error_free (error);
3801 
3802  /* Fallback to the system machine ID */
3803  _dbus_string_init_const (&filename, "/etc/machine-id");
3804  b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error);
3805 
3806  if (b)
3807  {
3808  /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not
3809  * complain if that isn't possible for whatever reason */
3810  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3811  _dbus_write_uuid_file (&filename, machine_id, NULL);
3812 
3813  return TRUE;
3814  }
3815 
3816  if (!create_if_not_found)
3817  return FALSE;
3818 
3819  /* if none found, try to make a new one */
3820  dbus_error_free (error);
3821  _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE);
3822 
3823  if (!_dbus_generate_uuid (machine_id, error))
3824  return FALSE;
3825 
3826  return _dbus_write_uuid_file (&filename, machine_id, error);
3827 }
3828 
3838  const char *launchd_env_var,
3839  DBusError *error)
3840 {
3841 #ifdef DBUS_ENABLE_LAUNCHD
3842  char *argv[4];
3843  int i;
3844 
3845  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3846 
3847  if (_dbus_check_setuid ())
3848  {
3850  "Unable to find launchd socket when setuid");
3851  return FALSE;
3852  }
3853 
3854  i = 0;
3855  argv[i] = "launchctl";
3856  ++i;
3857  argv[i] = "getenv";
3858  ++i;
3859  argv[i] = (char*)launchd_env_var;
3860  ++i;
3861  argv[i] = NULL;
3862  ++i;
3863 
3864  _dbus_assert (i == _DBUS_N_ELEMENTS (argv));
3865 
3866  if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error))
3867  {
3868  return FALSE;
3869  }
3870 
3871  /* no error, but no result either */
3872  if (_dbus_string_get_length(socket_path) == 0)
3873  {
3874  return FALSE;
3875  }
3876 
3877  /* strip the carriage-return */
3878  _dbus_string_shorten(socket_path, 1);
3879  return TRUE;
3880 #else /* DBUS_ENABLE_LAUNCHD */
3882  "can't lookup socket from launchd; launchd support not compiled in");
3883  return FALSE;
3884 #endif
3885 }
3886 
3887 #ifdef DBUS_ENABLE_LAUNCHD
3888 static dbus_bool_t
3889 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
3890 {
3891  dbus_bool_t valid_socket;
3892  DBusString socket_path;
3893 
3894  if (_dbus_check_setuid ())
3895  {
3897  "Unable to find launchd socket when setuid");
3898  return FALSE;
3899  }
3900 
3901  if (!_dbus_string_init (&socket_path))
3902  {
3903  _DBUS_SET_OOM (error);
3904  return FALSE;
3905  }
3906 
3907  valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error);
3908 
3909  if (dbus_error_is_set(error))
3910  {
3911  _dbus_string_free(&socket_path);
3912  return FALSE;
3913  }
3914 
3915  if (!valid_socket)
3916  {
3917  dbus_set_error(error, "no socket path",
3918  "launchd did not provide a socket path, "
3919  "verify that org.freedesktop.dbus-session.plist is loaded!");
3920  _dbus_string_free(&socket_path);
3921  return FALSE;
3922  }
3923  if (!_dbus_string_append (address, "unix:path="))
3924  {
3925  _DBUS_SET_OOM (error);
3926  _dbus_string_free(&socket_path);
3927  return FALSE;
3928  }
3929  if (!_dbus_string_copy (&socket_path, 0, address,
3930  _dbus_string_get_length (address)))
3931  {
3932  _DBUS_SET_OOM (error);
3933  _dbus_string_free(&socket_path);
3934  return FALSE;
3935  }
3936 
3937  _dbus_string_free(&socket_path);
3938  return TRUE;
3939 }
3940 #endif
3941 
3943 _dbus_lookup_user_bus (dbus_bool_t *supported,
3944  DBusString *address,
3945  DBusError *error)
3946 {
3947  const char *runtime_dir = _dbus_getenv ("XDG_RUNTIME_DIR");
3948  dbus_bool_t ret = FALSE;
3949  struct stat stbuf;
3950  DBusString user_bus_path;
3951 
3952  if (runtime_dir == NULL)
3953  {
3954  _dbus_verbose ("XDG_RUNTIME_DIR not found in environment");
3955  *supported = FALSE;
3956  return TRUE; /* Cannot use it, but not an error */
3957  }
3958 
3959  if (!_dbus_string_init (&user_bus_path))
3960  {
3961  _DBUS_SET_OOM (error);
3962  return FALSE;
3963  }
3964 
3965  if (!_dbus_string_append_printf (&user_bus_path, "%s/bus", runtime_dir))
3966  {
3967  _DBUS_SET_OOM (error);
3968  goto out;
3969  }
3970 
3971  if (lstat (_dbus_string_get_const_data (&user_bus_path), &stbuf) == -1)
3972  {
3973  _dbus_verbose ("XDG_RUNTIME_DIR/bus not available: %s",
3974  _dbus_strerror (errno));
3975  *supported = FALSE;
3976  ret = TRUE; /* Cannot use it, but not an error */
3977  goto out;
3978  }
3979 
3980  if (stbuf.st_uid != getuid ())
3981  {
3982  _dbus_verbose ("XDG_RUNTIME_DIR/bus owned by uid %ld, not our uid %ld",
3983  (long) stbuf.st_uid, (long) getuid ());
3984  *supported = FALSE;
3985  ret = TRUE; /* Cannot use it, but not an error */
3986  goto out;
3987  }
3988 
3989  if ((stbuf.st_mode & S_IFMT) != S_IFSOCK)
3990  {
3991  _dbus_verbose ("XDG_RUNTIME_DIR/bus is not a socket: st_mode = 0o%lo",
3992  (long) stbuf.st_mode);
3993  *supported = FALSE;
3994  ret = TRUE; /* Cannot use it, but not an error */
3995  goto out;
3996  }
3997 
3998  if (!_dbus_string_append (address, "unix:path=") ||
3999  !_dbus_address_append_escaped (address, &user_bus_path))
4000  {
4001  _DBUS_SET_OOM (error);
4002  goto out;
4003  }
4004 
4005  *supported = TRUE;
4006  ret = TRUE;
4007 
4008 out:
4009  _dbus_string_free (&user_bus_path);
4010  return ret;
4011 }
4012 
4034  DBusString *address,
4035  DBusError *error)
4036 {
4037 #ifdef DBUS_ENABLE_LAUNCHD
4038  *supported = TRUE;
4039  return _dbus_lookup_session_address_launchd (address, error);
4040 #else
4041  *supported = FALSE;
4042 
4043  if (!_dbus_lookup_user_bus (supported, address, error))
4044  return FALSE;
4045  else if (*supported)
4046  return TRUE;
4047 
4048  /* On non-Mac Unix platforms, if the session address isn't already
4049  * set in DBUS_SESSION_BUS_ADDRESS environment variable and the
4050  * $XDG_RUNTIME_DIR/bus can't be used, we punt and fall back to the
4051  * autolaunch: global default; see init_session_address in
4052  * dbus/dbus-bus.c. */
4053  return TRUE;
4054 #endif
4055 }
4056 
4064 void
4066 {
4068 }
4069 
4085  DBusCredentials *credentials)
4086 {
4087  DBusString homedir;
4088  DBusString dotdir;
4089  dbus_uid_t uid;
4090 
4091  _dbus_assert (credentials != NULL);
4093 
4094  if (!_dbus_string_init (&homedir))
4095  return FALSE;
4096 
4097  uid = _dbus_credentials_get_unix_uid (credentials);
4098  _dbus_assert (uid != DBUS_UID_UNSET);
4099 
4100  if (!_dbus_homedir_from_uid (uid, &homedir))
4101  goto failed;
4102 
4103 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
4104  {
4105  const char *override;
4106 
4107  override = _dbus_getenv ("DBUS_TEST_HOMEDIR");
4108  if (override != NULL && *override != '\0')
4109  {
4110  _dbus_string_set_length (&homedir, 0);
4111  if (!_dbus_string_append (&homedir, override))
4112  goto failed;
4113 
4114  _dbus_verbose ("Using fake homedir for testing: %s\n",
4115  _dbus_string_get_const_data (&homedir));
4116  }
4117  else
4118  {
4119  /* Not strictly thread-safe, but if we fail at thread-safety here,
4120  * the worst that will happen is some extra warnings. */
4121  static dbus_bool_t already_warned = FALSE;
4122  if (!already_warned)
4123  {
4124  _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n");
4125  already_warned = TRUE;
4126  }
4127  }
4128  }
4129 #endif
4130 
4131  _dbus_string_init_const (&dotdir, ".dbus-keyrings");
4132  if (!_dbus_concat_dir_and_file (&homedir,
4133  &dotdir))
4134  goto failed;
4135 
4136  if (!_dbus_string_copy (&homedir, 0,
4137  directory, _dbus_string_get_length (directory))) {
4138  goto failed;
4139  }
4140 
4141  _dbus_string_free (&homedir);
4142  return TRUE;
4143 
4144  failed:
4145  _dbus_string_free (&homedir);
4146  return FALSE;
4147 }
4148 
4149 //PENDING(kdab) docs
4151 _dbus_daemon_publish_session_bus_address (const char* addr,
4152  const char *scope)
4153 {
4154  return TRUE;
4155 }
4156 
4157 //PENDING(kdab) docs
4158 void
4159 _dbus_daemon_unpublish_session_bus_address (void)
4160 {
4161 
4162 }
4163 
4172 {
4173  return e == EAGAIN || e == EWOULDBLOCK;
4174 }
4175 
4185  DBusError *error)
4186 {
4187  const char *filename_c;
4188 
4189  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
4190 
4191  filename_c = _dbus_string_get_const_data (filename);
4192 
4193  if (rmdir (filename_c) != 0)
4194  {
4196  "Failed to remove directory %s: %s\n",
4197  filename_c, _dbus_strerror (errno));
4198  return FALSE;
4199  }
4200 
4201  return TRUE;
4202 }
4203 
4213 {
4214 #ifdef SCM_RIGHTS
4215  union {
4216  struct sockaddr sa;
4217  struct sockaddr_storage storage;
4218  struct sockaddr_un un;
4219  } sa_buf;
4220 
4221  socklen_t sa_len = sizeof(sa_buf);
4222 
4223  _DBUS_ZERO(sa_buf);
4224 
4225  if (getsockname(fd.fd, &sa_buf.sa, &sa_len) < 0)
4226  return FALSE;
4227 
4228  return sa_buf.sa.sa_family == AF_UNIX;
4229 
4230 #else
4231  return FALSE;
4232 
4233 #endif
4234 }
4235 
4240 void
4242 {
4243  int maxfds, i;
4244 
4245 #ifdef __linux__
4246  DIR *d;
4247 
4248  /* On Linux we can optimize this a bit if /proc is available. If it
4249  isn't available, fall back to the brute force way. */
4250 
4251  d = opendir ("/proc/self/fd");
4252  if (d)
4253  {
4254  for (;;)
4255  {
4256  struct dirent buf, *de;
4257  int k, fd;
4258  long l;
4259  char *e = NULL;
4260 
4261  k = readdir_r (d, &buf, &de);
4262  if (k != 0 || !de)
4263  break;
4264 
4265  if (de->d_name[0] == '.')
4266  continue;
4267 
4268  errno = 0;
4269  l = strtol (de->d_name, &e, 10);
4270  if (errno != 0 || e == NULL || *e != '\0')
4271  continue;
4272 
4273  fd = (int) l;
4274  if (fd < 3)
4275  continue;
4276 
4277  if (fd == dirfd (d))
4278  continue;
4279 
4280  close (fd);
4281  }
4282 
4283  closedir (d);
4284  return;
4285  }
4286 #endif
4287 
4288  maxfds = sysconf (_SC_OPEN_MAX);
4289 
4290  /* Pick something reasonable if for some reason sysconf says
4291  * unlimited.
4292  */
4293  if (maxfds < 0)
4294  maxfds = 1024;
4295 
4296  /* close all inherited fds */
4297  for (i = 3; i < maxfds; i++)
4298  close (i);
4299 }
4300 
4312 {
4313  /* TODO: get __libc_enable_secure exported from glibc.
4314  * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
4315  */
4316 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
4317  {
4318  /* See glibc/include/unistd.h */
4319  extern int __libc_enable_secure;
4320  return __libc_enable_secure;
4321  }
4322 #elif defined(HAVE_ISSETUGID)
4323  /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
4324  return issetugid ();
4325 #else
4326  uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
4327  gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
4328 
4329  /* We call into this function from _dbus_threads_init_platform_specific()
4330  * to make sure these are initialized before we start threading. */
4331  static dbus_bool_t check_setuid_initialised;
4332  static dbus_bool_t is_setuid;
4333 
4334  if (_DBUS_UNLIKELY (!check_setuid_initialised))
4335  {
4336 #ifdef HAVE_GETRESUID
4337  if (getresuid (&ruid, &euid, &suid) != 0 ||
4338  getresgid (&rgid, &egid, &sgid) != 0)
4339 #endif /* HAVE_GETRESUID */
4340  {
4341  suid = ruid = getuid ();
4342  sgid = rgid = getgid ();
4343  euid = geteuid ();
4344  egid = getegid ();
4345  }
4346 
4347  check_setuid_initialised = TRUE;
4348  is_setuid = (ruid != euid || ruid != suid ||
4349  rgid != egid || rgid != sgid);
4350 
4351  }
4352  return is_setuid;
4353 #endif
4354 }
4355 
4365  DBusString *address,
4366  DBusError *error)
4367 {
4368  union {
4369  struct sockaddr sa;
4370  struct sockaddr_storage storage;
4371  struct sockaddr_un un;
4372  struct sockaddr_in ipv4;
4373  struct sockaddr_in6 ipv6;
4374  } socket;
4375  char hostip[INET6_ADDRSTRLEN];
4376  int size = sizeof (socket);
4377  DBusString path_str;
4378 
4379  if (getsockname (fd.fd, &socket.sa, &size))
4380  goto err;
4381 
4382  switch (socket.sa.sa_family)
4383  {
4384  case AF_UNIX:
4385  if (socket.un.sun_path[0]=='\0')
4386  {
4387  _dbus_string_init_const (&path_str, &(socket.un.sun_path[1]));
4388  if (_dbus_string_append (address, "unix:abstract=") &&
4389  _dbus_address_append_escaped (address, &path_str))
4390  return TRUE;
4391  }
4392  else
4393  {
4394  _dbus_string_init_const (&path_str, socket.un.sun_path);
4395  if (_dbus_string_append (address, "unix:path=") &&
4396  _dbus_address_append_escaped (address, &path_str))
4397  return TRUE;
4398  }
4399  break;
4400  case AF_INET:
4401  if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
4402  if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
4403  hostip, ntohs (socket.ipv4.sin_port)))
4404  return TRUE;
4405  break;
4406 #ifdef AF_INET6
4407  case AF_INET6:
4408  _dbus_string_init_const (&path_str, hostip);
4409  if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
4410  if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
4411  ntohs (socket.ipv6.sin6_port)) &&
4412  _dbus_address_append_escaped (address, &path_str))
4413  return TRUE;
4414  break;
4415 #endif
4416  default:
4417  dbus_set_error (error,
4418  _dbus_error_from_errno (EINVAL),
4419  "Failed to read address from socket: Unknown socket type.");
4420  return FALSE;
4421  }
4422  err:
4423  dbus_set_error (error,
4424  _dbus_error_from_errno (errno),
4425  "Failed to open socket: %s",
4426  _dbus_strerror (errno));
4427  return FALSE;
4428 }
4429 
4430 int
4431 _dbus_save_socket_errno (void)
4432 {
4433  return errno;
4434 }
4435 
4436 void
4437 _dbus_restore_socket_errno (int saved_errno)
4438 {
4439  errno = saved_errno;
4440 }
4441 
4442 /* tests in dbus-sysdeps-util.c */
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:935
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_parse_int(const DBusString *str, int start, long *value_return, int *end_return)
Parses an integer contained in a DBusString.
Definition: dbus-sysdeps.c:435
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:279
dbus_uid_t _dbus_credentials_get_unix_uid(DBusCredentials *credentials)
Gets the UNIX user ID in the credentials, or DBUS_UID_UNSET if the credentials object doesn&#39;t contain...
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_append_uint(DBusString *str, unsigned long value)
Appends an unsigned integer to a DBusString.
Definition: dbus-sysdeps.c:392
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
char * username
Username.
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
volatile dbus_int32_t value
Value of the atomic integer.
Definition: dbus-sysdeps.h:284
dbus_bool_t _dbus_check_dir_is_private_to_user(DBusString *dir, DBusError *error)
Checks to make sure the given directory is private to the user.
void _dbus_close_all(void)
Closes all file descriptors except the first three (i.e.
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:601
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition: dbus-string.c:760
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
int _dbus_write(int fd, const DBusString *buffer, int start, int len)
Thin wrapper around the write() system call that writes a part of a DBusString and handles EINTR for ...
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn&#39;t supported (like ENOSYS on UNIX).
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:58
#define DBUS_GID_FORMAT
an appropriate printf format for dbus_gid_t
Definition: dbus-sysdeps.h:123
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:119
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t _dbus_append_address_from_socket(DBusSocket fd, DBusString *address, DBusError *error)
Read the address from the socket and append it to the string.
dbus_bool_t _dbus_check_setuid(void)
NOTE: If you modify this function, please also consider making the corresponding change in GLib...
void _dbus_user_database_flush_system(void)
Flushes the system global user database;.
Definition: dbus-userdb.c:349
void dbus_error_free(DBusError *error)
Frees an error that&#39;s been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
dbus_gid_t primary_gid
GID.
dbus_bool_t _dbus_credentials_add_linux_security_label(DBusCredentials *credentials, const char *label)
Add a Linux security label, as used by LSMs such as SELinux, Smack and AppArmor, to the credentials...
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:385
dbus_bool_t _dbus_concat_dir_and_file(DBusString *dir, const DBusString *next_component)
Appends the given filename to the given directory.
char * _dbus_string_get_data_len(DBusString *str, int start, int len)
Gets a sub-portion of the raw character buffer from the string.
Definition: dbus-string.c:490
int _dbus_read_socket(DBusSocket fd, DBusString *buffer, int count)
Like _dbus_read(), but only works on sockets so is available on Windows.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
#define DBUS_ERROR_IO_ERROR
Something went wrong reading or writing to a socket, for example.
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition: dbus-string.c:780
short events
Events to poll for.
Definition: dbus-sysdeps.h:380
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that&#39;s copied to the d...
Definition: dbus-string.c:1283
#define DBUS_PID_UNSET
an invalid PID used to represent an uninitialized dbus_pid_t field
Definition: dbus-sysdeps.h:112
dbus_bool_t _dbus_send_credentials_socket(DBusSocket server_fd, DBusError *error)
Sends a single nul byte with our UNIX credentials as ancillary data.
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
void _dbus_credentials_clear(DBusCredentials *credentials)
Clear all credentials in the object.
#define DBUS_UID_UNSET
an invalid UID used to represent an uninitialized dbus_uid_t field
Definition: dbus-sysdeps.h:114
dbus_bool_t _dbus_parse_uid(const DBusString *uid_str, dbus_uid_t *uid)
Gets a UID from a UID string.
dbus_bool_t _dbus_get_autolaunch_address(const char *scope, DBusString *address, DBusError *error)
Returns the address of a new session bus.
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
Definition: dbus-sysdeps.c:590
dbus_bool_t _dbus_user_info_fill(DBusUserInfo *info, const DBusString *username, DBusError *error)
Gets user info for the given username.
dbus_bool_t _dbus_homedir_from_uid(dbus_uid_t uid, DBusString *homedir)
Gets the home directory for the given user.
Definition: dbus-userdb.c:461
unsigned long dbus_pid_t
A process ID.
Definition: dbus-sysdeps.h:105
int _dbus_read_socket_with_unix_fds(DBusSocket fd, DBusString *buffer, int count, int *fds, int *n_fds)
Like _dbus_read_socket() but also tries to read unix fds from the socket.
Socket interface.
Definition: dbus-sysdeps.h:148
dbus_gid_t * group_ids
Groups IDs, including above primary group.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_lookup_launchd_socket(DBusString *socket_path, const char *launchd_env_var, DBusError *error)
quries launchd for a specific env var which holds the socket path.
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:461
dbus_bool_t _dbus_append_user_from_current_process(DBusString *str)
Append to the string the identity we would like to have when we authenticate, on UNIX this is the cur...
dbus_bool_t _dbus_credentials_are_anonymous(DBusCredentials *credentials)
Checks whether a credentials object contains a user identity.
dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock(int e)
See if errno is EAGAIN or EWOULDBLOCK (this has to be done differently for Winsock so is abstracted) ...
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
int n_group_ids
Size of group IDs array.
int _dbus_listen_systemd_sockets(DBusSocket **fds, DBusError *error)
Acquires one or more sockets passed in from systemd.
#define _DBUS_POLLOUT
Writing now will not block.
Definition: dbus-sysdeps.h:389
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
int _dbus_write_socket_two(DBusSocket fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write_two() but only works on sockets and is thus available on Windows.
DBusSocket _dbus_accept(DBusSocket listen_fd)
Accepts a connection on a listening socket.
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc...
Definition: dbus-string.c:132
dbus_uid_t uid
UID.
int _dbus_read(int fd, DBusString *buffer, int count)
Thin wrapper around the read() system call that appends the data it reads to the DBusString buffer...
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1114
dbus_bool_t _dbus_append_keyring_directory_for_credentials(DBusString *directory, DBusCredentials *credentials)
Appends the directory in which a keyring for the given credentials should be stored.
dbus_bool_t _dbus_read_credentials_socket(DBusSocket client_fd, DBusCredentials *credentials, DBusError *error)
Reads a single byte which must be nul (an error occurs otherwise), and reads unix credentials if avai...
dbus_bool_t _dbus_create_directory(const DBusString *filename, DBusError *error)
Creates a directory; succeeds if the directory is created or already existed.
dbus_bool_t _dbus_delete_directory(const DBusString *filename, DBusError *error)
Removes a directory; Directory must be empty.
Object representing an exception.
Definition: dbus-errors.h:48
dbus_bool_t _dbus_address_append_escaped(DBusString *escaped, const DBusString *unescaped)
Appends an escaped version of one string to another string, using the D-Bus address escaping mechanis...
Definition: dbus-address.c:104
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
int _dbus_listen_tcp_socket(const char *host, const char *port, const char *family, DBusString *retport, DBusSocket **fds_p, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
#define DBUS_ERROR_BAD_ADDRESS
A D-Bus bus address was malformed.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
dbus_bool_t _dbus_credentials_add_adt_audit_data(DBusCredentials *credentials, void *audit_data, dbus_int32_t size)
Add ADT audit data to the credentials.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
void _dbus_flush_caches(void)
Called when the bus daemon is signaled to reload its configuration; any caches should be nuked...
int _dbus_connect_exec(const char *path, char *const argv[], DBusError *error)
Creates a UNIX domain socket and connects it to the specified process to execute. ...
const char * _dbus_get_tmpdir(void)
Gets the temporary files directory by inspecting the environment variables TMPDIR, TMP, and TEMP in that order.
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1157
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
#define DBUS_GID_UNSET
an invalid GID used to represent an uninitialized dbus_gid_t field
Definition: dbus-sysdeps.h:116
dbus_uid_t _dbus_geteuid(void)
Gets our effective UID.
dbus_bool_t _dbus_credentials_add_from_current_process(DBusCredentials *credentials)
Adds the credentials of the current process to the passed-in credentials object.
#define TRUE
Expands to "1".
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:379
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
dbus_bool_t _dbus_credentials_add_pid(DBusCredentials *credentials, dbus_pid_t pid)
Add a UNIX process ID to the credentials.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:873
#define DBUS_UID_FORMAT
an appropriate printf format for dbus_uid_t
Definition: dbus-sysdeps.h:121
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
char * homedir
Home directory.
void _dbus_exit(int code)
Exit the process, returning the given value.
unsigned long _dbus_pid_for_log(void)
The only reason this is separate from _dbus_getpid() is to allow it on Windows for logging but not fo...
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
DBusSocket _dbus_connect_tcp_socket(const char *host, const char *port, const char *family, DBusError *error)
Creates a socket and connects to a socket at the given host and port.
dbus_uid_t _dbus_getuid(void)
Gets our UID.
dbus_bool_t _dbus_generate_random_bytes(DBusString *str, int n_bytes, DBusError *error)
Generates the given number of securely random bytes, using the best mechanism we can come up with...
dbus_bool_t _dbus_user_info_fill_uid(DBusUserInfo *info, dbus_uid_t uid, DBusError *error)
Gets user info for the given user ID.
dbus_bool_t _dbus_set_socket_nonblocking(DBusSocket fd, DBusError *error)
Sets a file descriptor to be nonblocking.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
dbus_bool_t _dbus_lookup_session_address(dbus_bool_t *supported, DBusString *address, DBusError *error)
Determines the address of the session bus by querying a platform-specific method. ...
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
#define FALSE
Expands to "0".
dbus_bool_t _dbus_read_local_machine_uuid(DBusGUID *machine_id, dbus_bool_t create_if_not_found, DBusError *error)
Reads the uuid of the machine we&#39;re running on from the dbus configuration.
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
void _dbus_print_backtrace(void)
On GNU libc systems, print a crude backtrace to stderr.
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:243
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
int _dbus_write_socket(DBusSocket fd, const DBusString *buffer, int start, int len)
Like _dbus_write(), but only supports sockets and is thus available on Windows.
int _dbus_write_two(int fd, const DBusString *buffer1, int start1, int len1, const DBusString *buffer2, int start2, int len2)
Like _dbus_write() but will use writev() if possible to write both buffers in sequence.
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
DBUS_PRIVATE_EXPORT void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:875
unsigned long dbus_gid_t
A group ID.
Definition: dbus-sysdeps.h:109
int _dbus_printf_string_upper_bound(const char *format, va_list args)
Measure the length of the given format string and arguments, not including the terminating nul...
char * _dbus_strdup(const char *str)
Duplicates a string.
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
dbus_bool_t _dbus_credentials_add_unix_uid(DBusCredentials *credentials, dbus_uid_t uid)
Add a UNIX user ID to the credentials.
dbus_bool_t _dbus_socket_can_pass_unix_fd(DBusSocket fd)
Checks whether file descriptors may be passed via the socket.
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
unsigned long dbus_uid_t
A user ID.
Definition: dbus-sysdeps.h:107
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
short revents
Events that occurred.
Definition: dbus-sysdeps.h:381
int _dbus_connect_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and connects it to the UNIX domain socket at the given path.
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329
int _dbus_listen_unix_socket(const char *path, dbus_bool_t abstract, DBusError *error)
Creates a socket and binds it to the given path, then listens on the socket.
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
Information about a UNIX user.
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:391