D-Bus: dbus-sysdeps-unix.c Source File

D-Bus 1.12.2

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