|
D-Bus
1.8.20
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. 00005 * Copyright (C) 2003 CodeFactory AB 00006 * 00007 * Licensed under the Academic Free License version 2.1 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 */ 00024 00025 #include <config.h> 00026 00027 #include "dbus-internals.h" 00028 #include "dbus-sysdeps.h" 00029 #include "dbus-sysdeps-unix.h" 00030 #include "dbus-threads.h" 00031 #include "dbus-protocol.h" 00032 #include "dbus-transport.h" 00033 #include "dbus-string.h" 00034 #include "dbus-userdb.h" 00035 #include "dbus-list.h" 00036 #include "dbus-credentials.h" 00037 #include "dbus-nonce.h" 00038 00039 #include <sys/types.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 #include <signal.h> 00043 #include <unistd.h> 00044 #include <stdio.h> 00045 #include <fcntl.h> 00046 #include <sys/socket.h> 00047 #include <dirent.h> 00048 #include <sys/un.h> 00049 #include <pwd.h> 00050 #include <time.h> 00051 #include <locale.h> 00052 #include <sys/time.h> 00053 #include <sys/stat.h> 00054 #include <sys/wait.h> 00055 #include <netinet/in.h> 00056 #include <netdb.h> 00057 #include <grp.h> 00058 #include <arpa/inet.h> 00059 #include <alloca.h> 00060 00061 #ifdef HAVE_ERRNO_H 00062 #include <errno.h> 00063 #endif 00064 #ifdef HAVE_WRITEV 00065 #include <sys/uio.h> 00066 #endif 00067 #ifdef HAVE_POLL 00068 #include <sys/poll.h> 00069 #endif 00070 #ifdef HAVE_BACKTRACE 00071 #include <execinfo.h> 00072 #endif 00073 #ifdef HAVE_GETPEERUCRED 00074 #include <ucred.h> 00075 #endif 00076 #ifdef HAVE_ALLOCA_H 00077 #include <alloca.h> 00078 #endif 00079 00080 #ifdef HAVE_ADT 00081 #include <bsm/adt.h> 00082 #endif 00083 00084 #include "sd-daemon.h" 00085 00086 #if !DBUS_USE_SYNC 00087 #include <pthread.h> 00088 #endif 00089 00090 #ifndef O_BINARY 00091 #define O_BINARY 0 00092 #endif 00093 00094 #ifndef AI_ADDRCONFIG 00095 #define AI_ADDRCONFIG 0 00096 #endif 00097 00098 #ifndef HAVE_SOCKLEN_T 00099 #define socklen_t int 00100 #endif 00101 00102 #if defined (__sun) || defined (__sun__) 00103 /* 00104 * CMS_SPACE etc. definitions for Solaris < 10, based on 00105 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html 00106 * via 00107 * http://wiki.opencsw.org/porting-faq#toc10 00108 * 00109 * These are only redefined for Solaris, for now: if your OS needs these too, 00110 * please file a bug. (Or preferably, improve your OS so they're not needed.) 00111 */ 00112 00113 # ifndef CMSG_ALIGN 00114 # ifdef __sun__ 00115 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len) 00116 # else 00117 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */ 00118 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \ 00119 ~(sizeof (long) - 1)) 00120 # endif 00121 # endif 00122 00123 # ifndef CMSG_SPACE 00124 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \ 00125 CMSG_ALIGN (len)) 00126 # endif 00127 00128 # ifndef CMSG_LEN 00129 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) 00130 # endif 00131 00132 #endif /* Solaris */ 00133 00134 static dbus_bool_t 00135 _dbus_open_socket (int *fd_p, 00136 int domain, 00137 int type, 00138 int protocol, 00139 DBusError *error) 00140 { 00141 #ifdef SOCK_CLOEXEC 00142 dbus_bool_t cloexec_done; 00143 00144 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol); 00145 cloexec_done = *fd_p >= 0; 00146 00147 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ 00148 if (*fd_p < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 00149 #endif 00150 { 00151 *fd_p = socket (domain, type, protocol); 00152 } 00153 00154 if (*fd_p >= 0) 00155 { 00156 #ifdef SOCK_CLOEXEC 00157 if (!cloexec_done) 00158 #endif 00159 { 00160 _dbus_fd_set_close_on_exec(*fd_p); 00161 } 00162 00163 _dbus_verbose ("socket fd %d opened\n", *fd_p); 00164 return TRUE; 00165 } 00166 else 00167 { 00168 dbus_set_error(error, 00169 _dbus_error_from_errno (errno), 00170 "Failed to open socket: %s", 00171 _dbus_strerror (errno)); 00172 return FALSE; 00173 } 00174 } 00175 00186 static dbus_bool_t 00187 _dbus_open_unix_socket (int *fd, 00188 DBusError *error) 00189 { 00190 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00191 } 00192 00201 dbus_bool_t 00202 _dbus_close_socket (int fd, 00203 DBusError *error) 00204 { 00205 return _dbus_close (fd, error); 00206 } 00207 00217 int 00218 _dbus_read_socket (int fd, 00219 DBusString *buffer, 00220 int count) 00221 { 00222 return _dbus_read (fd, buffer, count); 00223 } 00224 00235 int 00236 _dbus_write_socket (int fd, 00237 const DBusString *buffer, 00238 int start, 00239 int len) 00240 { 00241 #if HAVE_DECL_MSG_NOSIGNAL 00242 const char *data; 00243 int bytes_written; 00244 00245 data = _dbus_string_get_const_data_len (buffer, start, len); 00246 00247 again: 00248 00249 bytes_written = send (fd, data, len, MSG_NOSIGNAL); 00250 00251 if (bytes_written < 0 && errno == EINTR) 00252 goto again; 00253 00254 return bytes_written; 00255 00256 #else 00257 return _dbus_write (fd, buffer, start, len); 00258 #endif 00259 } 00260 00273 int 00274 _dbus_read_socket_with_unix_fds (int fd, 00275 DBusString *buffer, 00276 int count, 00277 int *fds, 00278 int *n_fds) { 00279 #ifndef HAVE_UNIX_FD_PASSING 00280 int r; 00281 00282 if ((r = _dbus_read_socket(fd, buffer, count)) < 0) 00283 return r; 00284 00285 *n_fds = 0; 00286 return r; 00287 00288 #else 00289 int bytes_read; 00290 int start; 00291 struct msghdr m; 00292 struct iovec iov; 00293 00294 _dbus_assert (count >= 0); 00295 _dbus_assert (*n_fds >= 0); 00296 00297 start = _dbus_string_get_length (buffer); 00298 00299 if (!_dbus_string_lengthen (buffer, count)) 00300 { 00301 errno = ENOMEM; 00302 return -1; 00303 } 00304 00305 _DBUS_ZERO(iov); 00306 iov.iov_base = _dbus_string_get_data_len (buffer, start, count); 00307 iov.iov_len = count; 00308 00309 _DBUS_ZERO(m); 00310 m.msg_iov = &iov; 00311 m.msg_iovlen = 1; 00312 00313 /* Hmm, we have no clue how long the control data will actually be 00314 that is queued for us. The least we can do is assume that the 00315 caller knows. Hence let's make space for the number of fds that 00316 we shall read at max plus the cmsg header. */ 00317 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int)); 00318 00319 /* It's probably safe to assume that systems with SCM_RIGHTS also 00320 know alloca() */ 00321 m.msg_control = alloca(m.msg_controllen); 00322 memset(m.msg_control, 0, m.msg_controllen); 00323 00324 /* Do not include the padding at the end when we tell the kernel 00325 * how much we're willing to receive. This avoids getting 00326 * the padding filled with additional fds that we weren't expecting, 00327 * if a (potentially malicious) sender included them. (fd.o #83622) */ 00328 m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int)); 00329 00330 again: 00331 00332 bytes_read = recvmsg(fd, &m, 0 00333 #ifdef MSG_CMSG_CLOEXEC 00334 |MSG_CMSG_CLOEXEC 00335 #endif 00336 ); 00337 00338 if (bytes_read < 0) 00339 { 00340 if (errno == EINTR) 00341 goto again; 00342 else 00343 { 00344 /* put length back (note that this doesn't actually realloc anything) */ 00345 _dbus_string_set_length (buffer, start); 00346 return -1; 00347 } 00348 } 00349 else 00350 { 00351 struct cmsghdr *cm; 00352 dbus_bool_t found = FALSE; 00353 00354 if (m.msg_flags & MSG_CTRUNC) 00355 { 00356 /* Hmm, apparently the control data was truncated. The bad 00357 thing is that we might have completely lost a couple of fds 00358 without chance to recover them. Hence let's treat this as a 00359 serious error. */ 00360 00361 errno = ENOSPC; 00362 _dbus_string_set_length (buffer, start); 00363 return -1; 00364 } 00365 00366 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00367 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00368 { 00369 size_t i; 00370 int *payload = (int *) CMSG_DATA (cm); 00371 size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0)); 00372 size_t payload_len_fds = payload_len_bytes / sizeof (int); 00373 size_t fds_to_use; 00374 00375 /* Every non-negative int fits in a size_t without truncation, 00376 * and we already know that *n_fds is non-negative, so 00377 * casting (size_t) *n_fds is OK */ 00378 _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int)); 00379 00380 if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds)) 00381 { 00382 /* The fds in the payload will fit in our buffer */ 00383 fds_to_use = payload_len_fds; 00384 } 00385 else 00386 { 00387 /* Too many fds in the payload. This shouldn't happen 00388 * any more because we're setting m.msg_controllen to 00389 * the exact number we can accept, but be safe and 00390 * truncate. */ 00391 fds_to_use = (size_t) *n_fds; 00392 00393 /* Close the excess fds to avoid DoS: if they stayed open, 00394 * someone could send us an extra fd per message 00395 * and we'd eventually run out. */ 00396 for (i = fds_to_use; i < payload_len_fds; i++) 00397 { 00398 close (payload[i]); 00399 } 00400 } 00401 00402 memcpy (fds, payload, fds_to_use * sizeof (int)); 00403 found = TRUE; 00404 /* This cannot overflow because we have chosen fds_to_use 00405 * to be <= *n_fds */ 00406 *n_fds = (int) fds_to_use; 00407 00408 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00409 worked, hence we need to go through this list and set 00410 CLOEXEC everywhere in any case */ 00411 for (i = 0; i < fds_to_use; i++) 00412 _dbus_fd_set_close_on_exec(fds[i]); 00413 00414 break; 00415 } 00416 00417 if (!found) 00418 *n_fds = 0; 00419 00420 /* put length back (doesn't actually realloc) */ 00421 _dbus_string_set_length (buffer, start + bytes_read); 00422 00423 #if 0 00424 if (bytes_read > 0) 00425 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00426 #endif 00427 00428 return bytes_read; 00429 } 00430 #endif 00431 } 00432 00433 int 00434 _dbus_write_socket_with_unix_fds(int fd, 00435 const DBusString *buffer, 00436 int start, 00437 int len, 00438 const int *fds, 00439 int n_fds) { 00440 00441 #ifndef HAVE_UNIX_FD_PASSING 00442 00443 if (n_fds > 0) { 00444 errno = ENOTSUP; 00445 return -1; 00446 } 00447 00448 return _dbus_write_socket(fd, buffer, start, len); 00449 #else 00450 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00451 #endif 00452 } 00453 00454 int 00455 _dbus_write_socket_with_unix_fds_two(int fd, 00456 const DBusString *buffer1, 00457 int start1, 00458 int len1, 00459 const DBusString *buffer2, 00460 int start2, 00461 int len2, 00462 const int *fds, 00463 int n_fds) { 00464 00465 #ifndef HAVE_UNIX_FD_PASSING 00466 00467 if (n_fds > 0) { 00468 errno = ENOTSUP; 00469 return -1; 00470 } 00471 00472 return _dbus_write_socket_two(fd, 00473 buffer1, start1, len1, 00474 buffer2, start2, len2); 00475 #else 00476 00477 struct msghdr m; 00478 struct cmsghdr *cm; 00479 struct iovec iov[2]; 00480 int bytes_written; 00481 00482 _dbus_assert (len1 >= 0); 00483 _dbus_assert (len2 >= 0); 00484 _dbus_assert (n_fds >= 0); 00485 00486 _DBUS_ZERO(iov); 00487 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00488 iov[0].iov_len = len1; 00489 00490 if (buffer2) 00491 { 00492 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00493 iov[1].iov_len = len2; 00494 } 00495 00496 _DBUS_ZERO(m); 00497 m.msg_iov = iov; 00498 m.msg_iovlen = buffer2 ? 2 : 1; 00499 00500 if (n_fds > 0) 00501 { 00502 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00503 m.msg_control = alloca(m.msg_controllen); 00504 memset(m.msg_control, 0, m.msg_controllen); 00505 00506 cm = CMSG_FIRSTHDR(&m); 00507 cm->cmsg_level = SOL_SOCKET; 00508 cm->cmsg_type = SCM_RIGHTS; 00509 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00510 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00511 } 00512 00513 again: 00514 00515 bytes_written = sendmsg (fd, &m, 0 00516 #if HAVE_DECL_MSG_NOSIGNAL 00517 |MSG_NOSIGNAL 00518 #endif 00519 ); 00520 00521 if (bytes_written < 0 && errno == EINTR) 00522 goto again; 00523 00524 #if 0 00525 if (bytes_written > 0) 00526 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00527 #endif 00528 00529 return bytes_written; 00530 #endif 00531 } 00532 00546 int 00547 _dbus_write_socket_two (int fd, 00548 const DBusString *buffer1, 00549 int start1, 00550 int len1, 00551 const DBusString *buffer2, 00552 int start2, 00553 int len2) 00554 { 00555 #if HAVE_DECL_MSG_NOSIGNAL 00556 struct iovec vectors[2]; 00557 const char *data1; 00558 const char *data2; 00559 int bytes_written; 00560 struct msghdr m; 00561 00562 _dbus_assert (buffer1 != NULL); 00563 _dbus_assert (start1 >= 0); 00564 _dbus_assert (start2 >= 0); 00565 _dbus_assert (len1 >= 0); 00566 _dbus_assert (len2 >= 0); 00567 00568 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00569 00570 if (buffer2 != NULL) 00571 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00572 else 00573 { 00574 data2 = NULL; 00575 start2 = 0; 00576 len2 = 0; 00577 } 00578 00579 vectors[0].iov_base = (char*) data1; 00580 vectors[0].iov_len = len1; 00581 vectors[1].iov_base = (char*) data2; 00582 vectors[1].iov_len = len2; 00583 00584 _DBUS_ZERO(m); 00585 m.msg_iov = vectors; 00586 m.msg_iovlen = data2 ? 2 : 1; 00587 00588 again: 00589 00590 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); 00591 00592 if (bytes_written < 0 && errno == EINTR) 00593 goto again; 00594 00595 return bytes_written; 00596 00597 #else 00598 return _dbus_write_two (fd, buffer1, start1, len1, 00599 buffer2, start2, len2); 00600 #endif 00601 } 00602 00603 dbus_bool_t 00604 _dbus_socket_is_invalid (int fd) 00605 { 00606 return fd < 0 ? TRUE : FALSE; 00607 } 00608 00625 int 00626 _dbus_read (int fd, 00627 DBusString *buffer, 00628 int count) 00629 { 00630 int bytes_read; 00631 int start; 00632 char *data; 00633 00634 _dbus_assert (count >= 0); 00635 00636 start = _dbus_string_get_length (buffer); 00637 00638 if (!_dbus_string_lengthen (buffer, count)) 00639 { 00640 errno = ENOMEM; 00641 return -1; 00642 } 00643 00644 data = _dbus_string_get_data_len (buffer, start, count); 00645 00646 again: 00647 00648 bytes_read = read (fd, data, count); 00649 00650 if (bytes_read < 0) 00651 { 00652 if (errno == EINTR) 00653 goto again; 00654 else 00655 { 00656 /* put length back (note that this doesn't actually realloc anything) */ 00657 _dbus_string_set_length (buffer, start); 00658 return -1; 00659 } 00660 } 00661 else 00662 { 00663 /* put length back (doesn't actually realloc) */ 00664 _dbus_string_set_length (buffer, start + bytes_read); 00665 00666 #if 0 00667 if (bytes_read > 0) 00668 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00669 #endif 00670 00671 return bytes_read; 00672 } 00673 } 00674 00685 int 00686 _dbus_write (int fd, 00687 const DBusString *buffer, 00688 int start, 00689 int len) 00690 { 00691 const char *data; 00692 int bytes_written; 00693 00694 data = _dbus_string_get_const_data_len (buffer, start, len); 00695 00696 again: 00697 00698 bytes_written = write (fd, data, len); 00699 00700 if (bytes_written < 0 && errno == EINTR) 00701 goto again; 00702 00703 #if 0 00704 if (bytes_written > 0) 00705 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00706 #endif 00707 00708 return bytes_written; 00709 } 00710 00731 int 00732 _dbus_write_two (int fd, 00733 const DBusString *buffer1, 00734 int start1, 00735 int len1, 00736 const DBusString *buffer2, 00737 int start2, 00738 int len2) 00739 { 00740 _dbus_assert (buffer1 != NULL); 00741 _dbus_assert (start1 >= 0); 00742 _dbus_assert (start2 >= 0); 00743 _dbus_assert (len1 >= 0); 00744 _dbus_assert (len2 >= 0); 00745 00746 #ifdef HAVE_WRITEV 00747 { 00748 struct iovec vectors[2]; 00749 const char *data1; 00750 const char *data2; 00751 int bytes_written; 00752 00753 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00754 00755 if (buffer2 != NULL) 00756 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00757 else 00758 { 00759 data2 = NULL; 00760 start2 = 0; 00761 len2 = 0; 00762 } 00763 00764 vectors[0].iov_base = (char*) data1; 00765 vectors[0].iov_len = len1; 00766 vectors[1].iov_base = (char*) data2; 00767 vectors[1].iov_len = len2; 00768 00769 again: 00770 00771 bytes_written = writev (fd, 00772 vectors, 00773 data2 ? 2 : 1); 00774 00775 if (bytes_written < 0 && errno == EINTR) 00776 goto again; 00777 00778 return bytes_written; 00779 } 00780 #else /* HAVE_WRITEV */ 00781 { 00782 int ret1, ret2; 00783 00784 ret1 = _dbus_write (fd, buffer1, start1, len1); 00785 if (ret1 == len1 && buffer2 != NULL) 00786 { 00787 ret2 = _dbus_write (fd, buffer2, start2, len2); 00788 if (ret2 < 0) 00789 ret2 = 0; /* we can't report an error as the first write was OK */ 00790 00791 return ret1 + ret2; 00792 } 00793 else 00794 return ret1; 00795 } 00796 #endif /* !HAVE_WRITEV */ 00797 } 00798 00799 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00800 00830 int 00831 _dbus_connect_unix_socket (const char *path, 00832 dbus_bool_t abstract, 00833 DBusError *error) 00834 { 00835 int fd; 00836 size_t path_len; 00837 struct sockaddr_un addr; 00838 00839 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00840 00841 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00842 path, abstract); 00843 00844 00845 if (!_dbus_open_unix_socket (&fd, error)) 00846 { 00847 _DBUS_ASSERT_ERROR_IS_SET(error); 00848 return -1; 00849 } 00850 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00851 00852 _DBUS_ZERO (addr); 00853 addr.sun_family = AF_UNIX; 00854 path_len = strlen (path); 00855 00856 if (abstract) 00857 { 00858 #ifdef HAVE_ABSTRACT_SOCKETS 00859 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00860 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00861 00862 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00863 { 00864 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00865 "Abstract socket name too long\n"); 00866 _dbus_close (fd, NULL); 00867 return -1; 00868 } 00869 00870 strncpy (&addr.sun_path[1], path, path_len); 00871 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00872 #else /* HAVE_ABSTRACT_SOCKETS */ 00873 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00874 "Operating system does not support abstract socket namespace\n"); 00875 _dbus_close (fd, NULL); 00876 return -1; 00877 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00878 } 00879 else 00880 { 00881 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00882 { 00883 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00884 "Socket name too long\n"); 00885 _dbus_close (fd, NULL); 00886 return -1; 00887 } 00888 00889 strncpy (addr.sun_path, path, path_len); 00890 } 00891 00892 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00893 { 00894 dbus_set_error (error, 00895 _dbus_error_from_errno (errno), 00896 "Failed to connect to socket %s: %s", 00897 path, _dbus_strerror (errno)); 00898 00899 _dbus_close (fd, NULL); 00900 return -1; 00901 } 00902 00903 if (!_dbus_set_fd_nonblocking (fd, error)) 00904 { 00905 _DBUS_ASSERT_ERROR_IS_SET (error); 00906 00907 _dbus_close (fd, NULL); 00908 return -1; 00909 } 00910 00911 return fd; 00912 } 00913 00926 int 00927 _dbus_connect_exec (const char *path, 00928 char *const argv[], 00929 DBusError *error) 00930 { 00931 int fds[2]; 00932 pid_t pid; 00933 int retval; 00934 dbus_bool_t cloexec_done = 0; 00935 00936 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00937 00938 _dbus_verbose ("connecting to process %s\n", path); 00939 00940 #ifdef SOCK_CLOEXEC 00941 retval = socketpair (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 00942 cloexec_done = (retval >= 0); 00943 00944 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 00945 #endif 00946 { 00947 retval = socketpair (AF_UNIX, SOCK_STREAM, 0, fds); 00948 } 00949 00950 if (retval < 0) 00951 { 00952 dbus_set_error (error, 00953 _dbus_error_from_errno (errno), 00954 "Failed to create socket pair: %s", 00955 _dbus_strerror (errno)); 00956 return -1; 00957 } 00958 00959 if (!cloexec_done) 00960 { 00961 _dbus_fd_set_close_on_exec (fds[0]); 00962 _dbus_fd_set_close_on_exec (fds[1]); 00963 } 00964 00965 pid = fork (); 00966 if (pid < 0) 00967 { 00968 dbus_set_error (error, 00969 _dbus_error_from_errno (errno), 00970 "Failed to fork() to call %s: %s", 00971 path, _dbus_strerror (errno)); 00972 close (fds[0]); 00973 close (fds[1]); 00974 return -1; 00975 } 00976 00977 if (pid == 0) 00978 { 00979 /* child */ 00980 close (fds[0]); 00981 00982 dup2 (fds[1], STDIN_FILENO); 00983 dup2 (fds[1], STDOUT_FILENO); 00984 00985 if (fds[1] != STDIN_FILENO && 00986 fds[1] != STDOUT_FILENO) 00987 close (fds[1]); 00988 00989 /* Inherit STDERR and the controlling terminal from the 00990 parent */ 00991 00992 _dbus_close_all (); 00993 00994 execvp (path, argv); 00995 00996 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno)); 00997 00998 _exit(1); 00999 } 01000 01001 /* parent */ 01002 close (fds[1]); 01003 01004 if (!_dbus_set_fd_nonblocking (fds[0], error)) 01005 { 01006 _DBUS_ASSERT_ERROR_IS_SET (error); 01007 01008 close (fds[0]); 01009 return -1; 01010 } 01011 01012 return fds[0]; 01013 } 01014 01032 int 01033 _dbus_listen_unix_socket (const char *path, 01034 dbus_bool_t abstract, 01035 DBusError *error) 01036 { 01037 int listen_fd; 01038 struct sockaddr_un addr; 01039 size_t path_len; 01040 01041 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01042 01043 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 01044 path, abstract); 01045 01046 if (!_dbus_open_unix_socket (&listen_fd, error)) 01047 { 01048 _DBUS_ASSERT_ERROR_IS_SET(error); 01049 return -1; 01050 } 01051 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01052 01053 _DBUS_ZERO (addr); 01054 addr.sun_family = AF_UNIX; 01055 path_len = strlen (path); 01056 01057 if (abstract) 01058 { 01059 #ifdef HAVE_ABSTRACT_SOCKETS 01060 /* remember that abstract names aren't nul-terminated so we rely 01061 * on sun_path being filled in with zeroes above. 01062 */ 01063 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 01064 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 01065 01066 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01067 { 01068 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01069 "Abstract socket name too long\n"); 01070 _dbus_close (listen_fd, NULL); 01071 return -1; 01072 } 01073 01074 strncpy (&addr.sun_path[1], path, path_len); 01075 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 01076 #else /* HAVE_ABSTRACT_SOCKETS */ 01077 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 01078 "Operating system does not support abstract socket namespace\n"); 01079 _dbus_close (listen_fd, NULL); 01080 return -1; 01081 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 01082 } 01083 else 01084 { 01085 /* Discussed security implications of this with Nalin, 01086 * and we couldn't think of where it would kick our ass, but 01087 * it still seems a bit sucky. It also has non-security suckage; 01088 * really we'd prefer to exit if the socket is already in use. 01089 * But there doesn't seem to be a good way to do this. 01090 * 01091 * Just to be extra careful, I threw in the stat() - clearly 01092 * the stat() can't *fix* any security issue, but it at least 01093 * avoids inadvertent/accidental data loss. 01094 */ 01095 { 01096 struct stat sb; 01097 01098 if (stat (path, &sb) == 0 && 01099 S_ISSOCK (sb.st_mode)) 01100 unlink (path); 01101 } 01102 01103 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01104 { 01105 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01106 "Abstract socket name too long\n"); 01107 _dbus_close (listen_fd, NULL); 01108 return -1; 01109 } 01110 01111 strncpy (addr.sun_path, path, path_len); 01112 } 01113 01114 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 01115 { 01116 dbus_set_error (error, _dbus_error_from_errno (errno), 01117 "Failed to bind socket \"%s\": %s", 01118 path, _dbus_strerror (errno)); 01119 _dbus_close (listen_fd, NULL); 01120 return -1; 01121 } 01122 01123 if (listen (listen_fd, 30 /* backlog */) < 0) 01124 { 01125 dbus_set_error (error, _dbus_error_from_errno (errno), 01126 "Failed to listen on socket \"%s\": %s", 01127 path, _dbus_strerror (errno)); 01128 _dbus_close (listen_fd, NULL); 01129 return -1; 01130 } 01131 01132 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01133 { 01134 _DBUS_ASSERT_ERROR_IS_SET (error); 01135 _dbus_close (listen_fd, NULL); 01136 return -1; 01137 } 01138 01139 /* Try opening up the permissions, but if we can't, just go ahead 01140 * and continue, maybe it will be good enough. 01141 */ 01142 if (!abstract && chmod (path, 0777) < 0) 01143 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01144 path); 01145 01146 return listen_fd; 01147 } 01148 01159 int 01160 _dbus_listen_systemd_sockets (int **fds, 01161 DBusError *error) 01162 { 01163 int r, n; 01164 unsigned fd; 01165 int *new_fds; 01166 01167 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01168 01169 n = sd_listen_fds (TRUE); 01170 if (n < 0) 01171 { 01172 dbus_set_error (error, _dbus_error_from_errno (-n), 01173 "Failed to acquire systemd socket: %s", 01174 _dbus_strerror (-n)); 01175 return -1; 01176 } 01177 01178 if (n <= 0) 01179 { 01180 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01181 "No socket received."); 01182 return -1; 01183 } 01184 01185 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01186 { 01187 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01188 if (r < 0) 01189 { 01190 dbus_set_error (error, _dbus_error_from_errno (-r), 01191 "Failed to verify systemd socket type: %s", 01192 _dbus_strerror (-r)); 01193 return -1; 01194 } 01195 01196 if (!r) 01197 { 01198 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01199 "Passed socket has wrong type."); 01200 return -1; 01201 } 01202 } 01203 01204 /* OK, the file descriptors are all good, so let's take posession of 01205 them then. */ 01206 01207 new_fds = dbus_new (int, n); 01208 if (!new_fds) 01209 { 01210 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01211 "Failed to allocate file handle array."); 01212 goto fail; 01213 } 01214 01215 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01216 { 01217 if (!_dbus_set_fd_nonblocking (fd, error)) 01218 { 01219 _DBUS_ASSERT_ERROR_IS_SET (error); 01220 goto fail; 01221 } 01222 01223 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01224 } 01225 01226 *fds = new_fds; 01227 return n; 01228 01229 fail: 01230 01231 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01232 { 01233 _dbus_close (fd, NULL); 01234 } 01235 01236 dbus_free (new_fds); 01237 return -1; 01238 } 01239 01253 int 01254 _dbus_connect_tcp_socket (const char *host, 01255 const char *port, 01256 const char *family, 01257 DBusError *error) 01258 { 01259 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01260 } 01261 01262 int 01263 _dbus_connect_tcp_socket_with_nonce (const char *host, 01264 const char *port, 01265 const char *family, 01266 const char *noncefile, 01267 DBusError *error) 01268 { 01269 int saved_errno = 0; 01270 int fd = -1, res; 01271 struct addrinfo hints; 01272 struct addrinfo *ai, *tmp; 01273 01274 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01275 01276 _DBUS_ZERO (hints); 01277 01278 if (!family) 01279 hints.ai_family = AF_UNSPEC; 01280 else if (!strcmp(family, "ipv4")) 01281 hints.ai_family = AF_INET; 01282 else if (!strcmp(family, "ipv6")) 01283 hints.ai_family = AF_INET6; 01284 else 01285 { 01286 dbus_set_error (error, 01287 DBUS_ERROR_BAD_ADDRESS, 01288 "Unknown address family %s", family); 01289 return -1; 01290 } 01291 hints.ai_protocol = IPPROTO_TCP; 01292 hints.ai_socktype = SOCK_STREAM; 01293 hints.ai_flags = AI_ADDRCONFIG; 01294 01295 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01296 { 01297 dbus_set_error (error, 01298 _dbus_error_from_errno (errno), 01299 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01300 host, port, gai_strerror(res), res); 01301 return -1; 01302 } 01303 01304 tmp = ai; 01305 while (tmp) 01306 { 01307 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01308 { 01309 freeaddrinfo(ai); 01310 _DBUS_ASSERT_ERROR_IS_SET(error); 01311 return -1; 01312 } 01313 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01314 01315 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01316 { 01317 saved_errno = errno; 01318 _dbus_close(fd, NULL); 01319 fd = -1; 01320 tmp = tmp->ai_next; 01321 continue; 01322 } 01323 01324 break; 01325 } 01326 freeaddrinfo(ai); 01327 01328 if (fd == -1) 01329 { 01330 dbus_set_error (error, 01331 _dbus_error_from_errno (saved_errno), 01332 "Failed to connect to socket \"%s:%s\" %s", 01333 host, port, _dbus_strerror(saved_errno)); 01334 return -1; 01335 } 01336 01337 if (noncefile != NULL) 01338 { 01339 DBusString noncefileStr; 01340 dbus_bool_t ret; 01341 _dbus_string_init_const (&noncefileStr, noncefile); 01342 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01343 _dbus_string_free (&noncefileStr); 01344 01345 if (!ret) 01346 { 01347 _dbus_close (fd, NULL); 01348 return -1; 01349 } 01350 } 01351 01352 if (!_dbus_set_fd_nonblocking (fd, error)) 01353 { 01354 _dbus_close (fd, NULL); 01355 return -1; 01356 } 01357 01358 return fd; 01359 } 01360 01377 int 01378 _dbus_listen_tcp_socket (const char *host, 01379 const char *port, 01380 const char *family, 01381 DBusString *retport, 01382 int **fds_p, 01383 DBusError *error) 01384 { 01385 int saved_errno; 01386 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01387 struct addrinfo hints; 01388 struct addrinfo *ai, *tmp; 01389 unsigned int reuseaddr; 01390 01391 *fds_p = NULL; 01392 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01393 01394 _DBUS_ZERO (hints); 01395 01396 if (!family) 01397 hints.ai_family = AF_UNSPEC; 01398 else if (!strcmp(family, "ipv4")) 01399 hints.ai_family = AF_INET; 01400 else if (!strcmp(family, "ipv6")) 01401 hints.ai_family = AF_INET6; 01402 else 01403 { 01404 dbus_set_error (error, 01405 DBUS_ERROR_BAD_ADDRESS, 01406 "Unknown address family %s", family); 01407 return -1; 01408 } 01409 01410 hints.ai_protocol = IPPROTO_TCP; 01411 hints.ai_socktype = SOCK_STREAM; 01412 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01413 01414 redo_lookup_with_port: 01415 ai = NULL; 01416 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01417 { 01418 dbus_set_error (error, 01419 _dbus_error_from_errno (errno), 01420 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01421 host ? host : "*", port, gai_strerror(res), res); 01422 goto failed; 01423 } 01424 01425 tmp = ai; 01426 while (tmp) 01427 { 01428 int fd = -1, *newlisten_fd; 01429 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01430 { 01431 _DBUS_ASSERT_ERROR_IS_SET(error); 01432 goto failed; 01433 } 01434 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01435 01436 reuseaddr = 1; 01437 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01438 { 01439 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01440 host ? host : "*", port, _dbus_strerror (errno)); 01441 } 01442 01443 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01444 { 01445 saved_errno = errno; 01446 _dbus_close(fd, NULL); 01447 if (saved_errno == EADDRINUSE) 01448 { 01449 /* Depending on kernel policy, it may or may not 01450 be neccessary to bind to both IPv4 & 6 addresses 01451 so ignore EADDRINUSE here */ 01452 tmp = tmp->ai_next; 01453 continue; 01454 } 01455 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01456 "Failed to bind socket \"%s:%s\": %s", 01457 host ? host : "*", port, _dbus_strerror (saved_errno)); 01458 goto failed; 01459 } 01460 01461 if (listen (fd, 30 /* backlog */) < 0) 01462 { 01463 saved_errno = errno; 01464 _dbus_close (fd, NULL); 01465 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01466 "Failed to listen on socket \"%s:%s\": %s", 01467 host ? host : "*", port, _dbus_strerror (saved_errno)); 01468 goto failed; 01469 } 01470 01471 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01472 if (!newlisten_fd) 01473 { 01474 saved_errno = errno; 01475 _dbus_close (fd, NULL); 01476 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01477 "Failed to allocate file handle array: %s", 01478 _dbus_strerror (saved_errno)); 01479 goto failed; 01480 } 01481 listen_fd = newlisten_fd; 01482 listen_fd[nlisten_fd] = fd; 01483 nlisten_fd++; 01484 01485 if (!_dbus_string_get_length(retport)) 01486 { 01487 /* If the user didn't specify a port, or used 0, then 01488 the kernel chooses a port. After the first address 01489 is bound to, we need to force all remaining addresses 01490 to use the same port */ 01491 if (!port || !strcmp(port, "0")) 01492 { 01493 int result; 01494 struct sockaddr_storage addr; 01495 socklen_t addrlen; 01496 char portbuf[50]; 01497 01498 addrlen = sizeof(addr); 01499 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01500 01501 if (result == -1 || 01502 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01503 portbuf, sizeof(portbuf), 01504 NI_NUMERICHOST)) != 0) 01505 { 01506 dbus_set_error (error, _dbus_error_from_errno (errno), 01507 "Failed to resolve port \"%s:%s\": %s (%s)", 01508 host ? host : "*", port, gai_strerror(res), res); 01509 goto failed; 01510 } 01511 if (!_dbus_string_append(retport, portbuf)) 01512 { 01513 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01514 goto failed; 01515 } 01516 01517 /* Release current address list & redo lookup */ 01518 port = _dbus_string_get_const_data(retport); 01519 freeaddrinfo(ai); 01520 goto redo_lookup_with_port; 01521 } 01522 else 01523 { 01524 if (!_dbus_string_append(retport, port)) 01525 { 01526 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01527 goto failed; 01528 } 01529 } 01530 } 01531 01532 tmp = tmp->ai_next; 01533 } 01534 freeaddrinfo(ai); 01535 ai = NULL; 01536 01537 if (!nlisten_fd) 01538 { 01539 errno = EADDRINUSE; 01540 dbus_set_error (error, _dbus_error_from_errno (errno), 01541 "Failed to bind socket \"%s:%s\": %s", 01542 host ? host : "*", port, _dbus_strerror (errno)); 01543 goto failed; 01544 } 01545 01546 for (i = 0 ; i < nlisten_fd ; i++) 01547 { 01548 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01549 { 01550 goto failed; 01551 } 01552 } 01553 01554 *fds_p = listen_fd; 01555 01556 return nlisten_fd; 01557 01558 failed: 01559 if (ai) 01560 freeaddrinfo(ai); 01561 for (i = 0 ; i < nlisten_fd ; i++) 01562 _dbus_close(listen_fd[i], NULL); 01563 dbus_free(listen_fd); 01564 return -1; 01565 } 01566 01567 static dbus_bool_t 01568 write_credentials_byte (int server_fd, 01569 DBusError *error) 01570 { 01571 int bytes_written; 01572 char buf[1] = { '\0' }; 01573 #if defined(HAVE_CMSGCRED) 01574 union { 01575 struct cmsghdr hdr; 01576 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01577 } cmsg; 01578 struct iovec iov; 01579 struct msghdr msg; 01580 iov.iov_base = buf; 01581 iov.iov_len = 1; 01582 01583 _DBUS_ZERO(msg); 01584 msg.msg_iov = &iov; 01585 msg.msg_iovlen = 1; 01586 01587 msg.msg_control = (caddr_t) &cmsg; 01588 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01589 _DBUS_ZERO(cmsg); 01590 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01591 cmsg.hdr.cmsg_level = SOL_SOCKET; 01592 cmsg.hdr.cmsg_type = SCM_CREDS; 01593 #endif 01594 01595 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01596 01597 again: 01598 01599 #if defined(HAVE_CMSGCRED) 01600 bytes_written = sendmsg (server_fd, &msg, 0 01601 #if HAVE_DECL_MSG_NOSIGNAL 01602 |MSG_NOSIGNAL 01603 #endif 01604 ); 01605 01606 /* If we HAVE_CMSGCRED, the OS still might not let us sendmsg() 01607 * with a SOL_SOCKET/SCM_CREDS message - for instance, FreeBSD 01608 * only allows that on AF_UNIX. Try just doing a send() instead. */ 01609 if (bytes_written < 0 && errno == EINVAL) 01610 #endif 01611 { 01612 bytes_written = send (server_fd, buf, 1, 0 01613 #if HAVE_DECL_MSG_NOSIGNAL 01614 |MSG_NOSIGNAL 01615 #endif 01616 ); 01617 } 01618 01619 if (bytes_written < 0 && errno == EINTR) 01620 goto again; 01621 01622 if (bytes_written < 0) 01623 { 01624 dbus_set_error (error, _dbus_error_from_errno (errno), 01625 "Failed to write credentials byte: %s", 01626 _dbus_strerror (errno)); 01627 return FALSE; 01628 } 01629 else if (bytes_written == 0) 01630 { 01631 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01632 "wrote zero bytes writing credentials byte"); 01633 return FALSE; 01634 } 01635 else 01636 { 01637 _dbus_assert (bytes_written == 1); 01638 _dbus_verbose ("wrote credentials byte\n"); 01639 return TRUE; 01640 } 01641 } 01642 01664 dbus_bool_t 01665 _dbus_read_credentials_socket (int client_fd, 01666 DBusCredentials *credentials, 01667 DBusError *error) 01668 { 01669 struct msghdr msg; 01670 struct iovec iov; 01671 char buf; 01672 dbus_uid_t uid_read; 01673 dbus_pid_t pid_read; 01674 int bytes_read; 01675 01676 #ifdef HAVE_CMSGCRED 01677 union { 01678 struct cmsghdr hdr; 01679 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01680 } cmsg; 01681 #endif 01682 01683 uid_read = DBUS_UID_UNSET; 01684 pid_read = DBUS_PID_UNSET; 01685 01686 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01687 01688 /* The POSIX spec certainly doesn't promise this, but 01689 * we need these assertions to fail as soon as we're wrong about 01690 * it so we can do the porting fixups 01691 */ 01692 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01693 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01694 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01695 01696 _dbus_credentials_clear (credentials); 01697 01698 iov.iov_base = &buf; 01699 iov.iov_len = 1; 01700 01701 _DBUS_ZERO(msg); 01702 msg.msg_iov = &iov; 01703 msg.msg_iovlen = 1; 01704 01705 #if defined(HAVE_CMSGCRED) 01706 _DBUS_ZERO(cmsg); 01707 msg.msg_control = (caddr_t) &cmsg; 01708 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01709 #endif 01710 01711 again: 01712 bytes_read = recvmsg (client_fd, &msg, 0); 01713 01714 if (bytes_read < 0) 01715 { 01716 if (errno == EINTR) 01717 goto again; 01718 01719 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01720 * normally only call read_credentials if the socket was ready 01721 * for reading 01722 */ 01723 01724 dbus_set_error (error, _dbus_error_from_errno (errno), 01725 "Failed to read credentials byte: %s", 01726 _dbus_strerror (errno)); 01727 return FALSE; 01728 } 01729 else if (bytes_read == 0) 01730 { 01731 /* this should not happen unless we are using recvmsg wrong, 01732 * so is essentially here for paranoia 01733 */ 01734 dbus_set_error (error, DBUS_ERROR_FAILED, 01735 "Failed to read credentials byte (zero-length read)"); 01736 return FALSE; 01737 } 01738 else if (buf != '\0') 01739 { 01740 dbus_set_error (error, DBUS_ERROR_FAILED, 01741 "Credentials byte was not nul"); 01742 return FALSE; 01743 } 01744 01745 _dbus_verbose ("read credentials byte\n"); 01746 01747 { 01748 #ifdef SO_PEERCRED 01749 /* Supported by at least Linux and OpenBSD, with minor differences. 01750 * 01751 * This mechanism passes the process ID through and does not require 01752 * the peer's cooperation, so we prefer it over all others. Notably, 01753 * Linux also supports SCM_CREDENTIALS, which is similar to FreeBSD 01754 * SCM_CREDS; it's implemented in GIO, but we don't use it in dbus at all, 01755 * because this is much less fragile. 01756 */ 01757 #ifdef __OpenBSD__ 01758 struct sockpeercred cr; 01759 #else 01760 struct ucred cr; 01761 #endif 01762 int cr_len = sizeof (cr); 01763 01764 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01765 cr_len == sizeof (cr)) 01766 { 01767 pid_read = cr.pid; 01768 uid_read = cr.uid; 01769 } 01770 else 01771 { 01772 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01773 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01774 } 01775 #elif defined(HAVE_CMSGCRED) 01776 /* We only check for HAVE_CMSGCRED, but we're really assuming that the 01777 * presence of that struct implies SCM_CREDS. Supported by at least 01778 * FreeBSD and DragonflyBSD. 01779 * 01780 * This mechanism requires the peer to help us (it has to send us a 01781 * SCM_CREDS message) but it does pass the process ID through, 01782 * which makes it better than getpeereid(). 01783 */ 01784 struct cmsgcred *cred; 01785 struct cmsghdr *cmsgp; 01786 01787 for (cmsgp = CMSG_FIRSTHDR (&msg); 01788 cmsgp != NULL; 01789 cmsgp = CMSG_NXTHDR (&msg, cmsgp)) 01790 { 01791 if (cmsgp->cmsg_type == SCM_CREDS && 01792 cmsgp->cmsg_level == SOL_SOCKET && 01793 cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred))) 01794 { 01795 cred = (struct cmsgcred *) CMSG_DATA (cmsgp); 01796 pid_read = cred->cmcred_pid; 01797 uid_read = cred->cmcred_euid; 01798 break; 01799 } 01800 } 01801 01802 #elif defined(HAVE_GETPEERUCRED) 01803 /* Supported in at least Solaris >= 10. It should probably be higher 01804 * up this list, because it carries the pid and we use this code path 01805 * for audit data. */ 01806 ucred_t * ucred = NULL; 01807 if (getpeerucred (client_fd, &ucred) == 0) 01808 { 01809 pid_read = ucred_getpid (ucred); 01810 uid_read = ucred_geteuid (ucred); 01811 #ifdef HAVE_ADT 01812 /* generate audit session data based on socket ucred */ 01813 adt_session_data_t *adth = NULL; 01814 adt_export_data_t *data = NULL; 01815 size_t size = 0; 01816 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01817 { 01818 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01819 } 01820 else 01821 { 01822 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01823 { 01824 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01825 } 01826 else 01827 { 01828 size = adt_export_session_data (adth, &data); 01829 if (size <= 0) 01830 { 01831 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01832 } 01833 else 01834 { 01835 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01836 free (data); 01837 } 01838 } 01839 (void) adt_end_session (adth); 01840 } 01841 #endif /* HAVE_ADT */ 01842 } 01843 else 01844 { 01845 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01846 } 01847 if (ucred != NULL) 01848 ucred_free (ucred); 01849 01850 /* ---------------------------------------------------------------- 01851 * When adding new mechanisms, please add them above this point 01852 * if they support passing the process ID through, or below if not. 01853 * ---------------------------------------------------------------- */ 01854 01855 #elif defined(HAVE_GETPEEREID) 01856 /* getpeereid() originates from D.J. Bernstein and is fairly 01857 * widely-supported. According to a web search, it might be present in 01858 * any/all of: 01859 * 01860 * - AIX? 01861 * - Blackberry? 01862 * - Cygwin 01863 * - FreeBSD 4.6+ (but we prefer SCM_CREDS: it carries the pid) 01864 * - Mac OS X 01865 * - Minix 3.1.8+ 01866 * - MirBSD? 01867 * - NetBSD 5.0+ (but LOCAL_PEEREID would be better: it carries the pid) 01868 * - OpenBSD 3.0+ (but we prefer SO_PEERCRED: it carries the pid) 01869 * - QNX? 01870 */ 01871 uid_t euid; 01872 gid_t egid; 01873 if (getpeereid (client_fd, &euid, &egid) == 0) 01874 { 01875 uid_read = euid; 01876 } 01877 else 01878 { 01879 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01880 } 01881 #else /* no supported mechanism */ 01882 01883 #warning Socket credentials not supported on this Unix OS 01884 #warning Please tell https://bugs.freedesktop.org/enter_bug.cgi?product=DBus 01885 01886 /* Please add other operating systems known to support at least one of 01887 * the mechanisms above to this list, keeping alphabetical order. 01888 * Everything not in this list is best-effort. 01889 */ 01890 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ 01891 defined(__linux__) || \ 01892 defined(__OpenBSD__) || \ 01893 defined(__NetBSD__) 01894 # error Credentials passing not working on this OS is a regression! 01895 #endif 01896 01897 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01898 #endif 01899 } 01900 01901 _dbus_verbose ("Credentials:" 01902 " pid "DBUS_PID_FORMAT 01903 " uid "DBUS_UID_FORMAT 01904 "\n", 01905 pid_read, 01906 uid_read); 01907 01908 if (pid_read != DBUS_PID_UNSET) 01909 { 01910 if (!_dbus_credentials_add_pid (credentials, pid_read)) 01911 { 01912 _DBUS_SET_OOM (error); 01913 return FALSE; 01914 } 01915 } 01916 01917 if (uid_read != DBUS_UID_UNSET) 01918 { 01919 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01920 { 01921 _DBUS_SET_OOM (error); 01922 return FALSE; 01923 } 01924 } 01925 01926 return TRUE; 01927 } 01928 01946 dbus_bool_t 01947 _dbus_send_credentials_socket (int server_fd, 01948 DBusError *error) 01949 { 01950 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01951 01952 if (write_credentials_byte (server_fd, error)) 01953 return TRUE; 01954 else 01955 return FALSE; 01956 } 01957 01967 int 01968 _dbus_accept (int listen_fd) 01969 { 01970 int client_fd; 01971 struct sockaddr addr; 01972 socklen_t addrlen; 01973 #ifdef HAVE_ACCEPT4 01974 dbus_bool_t cloexec_done; 01975 #endif 01976 01977 addrlen = sizeof (addr); 01978 01979 retry: 01980 01981 #ifdef HAVE_ACCEPT4 01982 /* 01983 * At compile-time, we assume that if accept4() is available in 01984 * libc headers, SOCK_CLOEXEC is too. At runtime, it is still 01985 * not necessarily true that either is supported by the running kernel. 01986 */ 01987 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01988 cloexec_done = client_fd >= 0; 01989 01990 if (client_fd < 0 && (errno == ENOSYS || errno == EINVAL)) 01991 #endif 01992 { 01993 client_fd = accept (listen_fd, &addr, &addrlen); 01994 } 01995 01996 if (client_fd < 0) 01997 { 01998 if (errno == EINTR) 01999 goto retry; 02000 } 02001 02002 _dbus_verbose ("client fd %d accepted\n", client_fd); 02003 02004 #ifdef HAVE_ACCEPT4 02005 if (!cloexec_done) 02006 #endif 02007 { 02008 _dbus_fd_set_close_on_exec(client_fd); 02009 } 02010 02011 return client_fd; 02012 } 02013 02022 dbus_bool_t 02023 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 02024 { 02025 const char *directory; 02026 struct stat sb; 02027 02028 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02029 02030 directory = _dbus_string_get_const_data (dir); 02031 02032 if (stat (directory, &sb) < 0) 02033 { 02034 dbus_set_error (error, _dbus_error_from_errno (errno), 02035 "%s", _dbus_strerror (errno)); 02036 02037 return FALSE; 02038 } 02039 02040 if (sb.st_uid != geteuid ()) 02041 { 02042 dbus_set_error (error, DBUS_ERROR_FAILED, 02043 "%s directory is owned by user %lu, not %lu", 02044 directory, 02045 (unsigned long) sb.st_uid, 02046 (unsigned long) geteuid ()); 02047 return FALSE; 02048 } 02049 02050 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 02051 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 02052 { 02053 dbus_set_error (error, DBUS_ERROR_FAILED, 02054 "%s directory is not private to the user", directory); 02055 return FALSE; 02056 } 02057 02058 return TRUE; 02059 } 02060 02061 static dbus_bool_t 02062 fill_user_info_from_passwd (struct passwd *p, 02063 DBusUserInfo *info, 02064 DBusError *error) 02065 { 02066 _dbus_assert (p->pw_name != NULL); 02067 _dbus_assert (p->pw_dir != NULL); 02068 02069 info->uid = p->pw_uid; 02070 info->primary_gid = p->pw_gid; 02071 info->username = _dbus_strdup (p->pw_name); 02072 info->homedir = _dbus_strdup (p->pw_dir); 02073 02074 if (info->username == NULL || 02075 info->homedir == NULL) 02076 { 02077 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02078 return FALSE; 02079 } 02080 02081 return TRUE; 02082 } 02083 02084 static dbus_bool_t 02085 fill_user_info (DBusUserInfo *info, 02086 dbus_uid_t uid, 02087 const DBusString *username, 02088 DBusError *error) 02089 { 02090 const char *username_c; 02091 02092 /* exactly one of username/uid provided */ 02093 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 02094 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 02095 02096 info->uid = DBUS_UID_UNSET; 02097 info->primary_gid = DBUS_GID_UNSET; 02098 info->group_ids = NULL; 02099 info->n_group_ids = 0; 02100 info->username = NULL; 02101 info->homedir = NULL; 02102 02103 if (username != NULL) 02104 username_c = _dbus_string_get_const_data (username); 02105 else 02106 username_c = NULL; 02107 02108 /* For now assuming that the getpwnam() and getpwuid() flavors 02109 * are always symmetrical, if not we have to add more configure 02110 * checks 02111 */ 02112 02113 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 02114 { 02115 struct passwd *p; 02116 int result; 02117 size_t buflen; 02118 char *buf; 02119 struct passwd p_str; 02120 02121 /* retrieve maximum needed size for buf */ 02122 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 02123 02124 /* sysconf actually returns a long, but everything else expects size_t, 02125 * so just recast here. 02126 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 02127 */ 02128 if ((long) buflen <= 0) 02129 buflen = 1024; 02130 02131 result = -1; 02132 while (1) 02133 { 02134 buf = dbus_malloc (buflen); 02135 if (buf == NULL) 02136 { 02137 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02138 return FALSE; 02139 } 02140 02141 p = NULL; 02142 #ifdef HAVE_POSIX_GETPWNAM_R 02143 if (uid != DBUS_UID_UNSET) 02144 result = getpwuid_r (uid, &p_str, buf, buflen, 02145 &p); 02146 else 02147 result = getpwnam_r (username_c, &p_str, buf, buflen, 02148 &p); 02149 #else 02150 if (uid != DBUS_UID_UNSET) 02151 p = getpwuid_r (uid, &p_str, buf, buflen); 02152 else 02153 p = getpwnam_r (username_c, &p_str, buf, buflen); 02154 result = 0; 02155 #endif /* !HAVE_POSIX_GETPWNAM_R */ 02156 //Try a bigger buffer if ERANGE was returned 02157 if (result == ERANGE && buflen < 512 * 1024) 02158 { 02159 dbus_free (buf); 02160 buflen *= 2; 02161 } 02162 else 02163 { 02164 break; 02165 } 02166 } 02167 if (result == 0 && p == &p_str) 02168 { 02169 if (!fill_user_info_from_passwd (p, info, error)) 02170 { 02171 dbus_free (buf); 02172 return FALSE; 02173 } 02174 dbus_free (buf); 02175 } 02176 else 02177 { 02178 dbus_set_error (error, _dbus_error_from_errno (errno), 02179 "User \"%s\" unknown or no memory to allocate password entry\n", 02180 username_c ? username_c : "???"); 02181 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02182 dbus_free (buf); 02183 return FALSE; 02184 } 02185 } 02186 #else /* ! HAVE_GETPWNAM_R */ 02187 { 02188 /* I guess we're screwed on thread safety here */ 02189 struct passwd *p; 02190 02191 if (uid != DBUS_UID_UNSET) 02192 p = getpwuid (uid); 02193 else 02194 p = getpwnam (username_c); 02195 02196 if (p != NULL) 02197 { 02198 if (!fill_user_info_from_passwd (p, info, error)) 02199 { 02200 return FALSE; 02201 } 02202 } 02203 else 02204 { 02205 dbus_set_error (error, _dbus_error_from_errno (errno), 02206 "User \"%s\" unknown or no memory to allocate password entry\n", 02207 username_c ? username_c : "???"); 02208 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02209 return FALSE; 02210 } 02211 } 02212 #endif /* ! HAVE_GETPWNAM_R */ 02213 02214 /* Fill this in so we can use it to get groups */ 02215 username_c = info->username; 02216 02217 #ifdef HAVE_GETGROUPLIST 02218 { 02219 gid_t *buf; 02220 int buf_count; 02221 int i; 02222 int initial_buf_count; 02223 02224 initial_buf_count = 17; 02225 buf_count = initial_buf_count; 02226 buf = dbus_new (gid_t, buf_count); 02227 if (buf == NULL) 02228 { 02229 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02230 goto failed; 02231 } 02232 02233 if (getgrouplist (username_c, 02234 info->primary_gid, 02235 buf, &buf_count) < 0) 02236 { 02237 gid_t *new; 02238 /* Presumed cause of negative return code: buf has insufficient 02239 entries to hold the entire group list. The Linux behavior in this 02240 case is to pass back the actual number of groups in buf_count, but 02241 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02242 So as a hack, try to help out a bit by guessing a larger 02243 number of groups, within reason.. might still fail, of course, 02244 but we can at least print a more informative message. I looked up 02245 the "right way" to do this by downloading Apple's own source code 02246 for the "id" command, and it turns out that they use an 02247 undocumented library function getgrouplist_2 (!) which is not 02248 declared in any header in /usr/include (!!). That did not seem 02249 like the way to go here. 02250 */ 02251 if (buf_count == initial_buf_count) 02252 { 02253 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02254 } 02255 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02256 if (new == NULL) 02257 { 02258 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02259 dbus_free (buf); 02260 goto failed; 02261 } 02262 02263 buf = new; 02264 02265 errno = 0; 02266 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02267 { 02268 if (errno == 0) 02269 { 02270 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02271 username_c, buf_count, buf_count); 02272 } 02273 else 02274 { 02275 dbus_set_error (error, 02276 _dbus_error_from_errno (errno), 02277 "Failed to get groups for username \"%s\" primary GID " 02278 DBUS_GID_FORMAT ": %s\n", 02279 username_c, info->primary_gid, 02280 _dbus_strerror (errno)); 02281 dbus_free (buf); 02282 goto failed; 02283 } 02284 } 02285 } 02286 02287 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02288 if (info->group_ids == NULL) 02289 { 02290 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02291 dbus_free (buf); 02292 goto failed; 02293 } 02294 02295 for (i = 0; i < buf_count; ++i) 02296 info->group_ids[i] = buf[i]; 02297 02298 info->n_group_ids = buf_count; 02299 02300 dbus_free (buf); 02301 } 02302 #else /* HAVE_GETGROUPLIST */ 02303 { 02304 /* We just get the one group ID */ 02305 info->group_ids = dbus_new (dbus_gid_t, 1); 02306 if (info->group_ids == NULL) 02307 { 02308 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02309 goto failed; 02310 } 02311 02312 info->n_group_ids = 1; 02313 02314 (info->group_ids)[0] = info->primary_gid; 02315 } 02316 #endif /* HAVE_GETGROUPLIST */ 02317 02318 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02319 02320 return TRUE; 02321 02322 failed: 02323 _DBUS_ASSERT_ERROR_IS_SET (error); 02324 return FALSE; 02325 } 02326 02335 dbus_bool_t 02336 _dbus_user_info_fill (DBusUserInfo *info, 02337 const DBusString *username, 02338 DBusError *error) 02339 { 02340 return fill_user_info (info, DBUS_UID_UNSET, 02341 username, error); 02342 } 02343 02352 dbus_bool_t 02353 _dbus_user_info_fill_uid (DBusUserInfo *info, 02354 dbus_uid_t uid, 02355 DBusError *error) 02356 { 02357 return fill_user_info (info, uid, 02358 NULL, error); 02359 } 02360 02368 dbus_bool_t 02369 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02370 { 02371 /* The POSIX spec certainly doesn't promise this, but 02372 * we need these assertions to fail as soon as we're wrong about 02373 * it so we can do the porting fixups 02374 */ 02375 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02376 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02377 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02378 02379 if (!_dbus_credentials_add_pid(credentials, _dbus_getpid())) 02380 return FALSE; 02381 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02382 return FALSE; 02383 02384 return TRUE; 02385 } 02386 02398 dbus_bool_t 02399 _dbus_append_user_from_current_process (DBusString *str) 02400 { 02401 return _dbus_string_append_uint (str, 02402 _dbus_geteuid ()); 02403 } 02404 02409 dbus_pid_t 02410 _dbus_getpid (void) 02411 { 02412 return getpid (); 02413 } 02414 02418 dbus_uid_t 02419 _dbus_getuid (void) 02420 { 02421 return getuid (); 02422 } 02423 02427 dbus_uid_t 02428 _dbus_geteuid (void) 02429 { 02430 return geteuid (); 02431 } 02432 02439 unsigned long 02440 _dbus_pid_for_log (void) 02441 { 02442 return getpid (); 02443 } 02444 02452 dbus_bool_t 02453 _dbus_parse_uid (const DBusString *uid_str, 02454 dbus_uid_t *uid) 02455 { 02456 int end; 02457 long val; 02458 02459 if (_dbus_string_get_length (uid_str) == 0) 02460 { 02461 _dbus_verbose ("UID string was zero length\n"); 02462 return FALSE; 02463 } 02464 02465 val = -1; 02466 end = 0; 02467 if (!_dbus_string_parse_int (uid_str, 0, &val, 02468 &end)) 02469 { 02470 _dbus_verbose ("could not parse string as a UID\n"); 02471 return FALSE; 02472 } 02473 02474 if (end != _dbus_string_get_length (uid_str)) 02475 { 02476 _dbus_verbose ("string contained trailing stuff after UID\n"); 02477 return FALSE; 02478 } 02479 02480 *uid = val; 02481 02482 return TRUE; 02483 } 02484 02485 #if !DBUS_USE_SYNC 02486 /* To be thread-safe by default on platforms that don't necessarily have 02487 * atomic operations (notably Debian armel, which is armv4t), we must 02488 * use a mutex that can be initialized statically, like this. 02489 * GLib >= 2.32 uses a similar system. 02490 */ 02491 static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER; 02492 #endif 02493 02500 dbus_int32_t 02501 _dbus_atomic_inc (DBusAtomic *atomic) 02502 { 02503 #if DBUS_USE_SYNC 02504 return __sync_add_and_fetch(&atomic->value, 1)-1; 02505 #else 02506 dbus_int32_t res; 02507 02508 pthread_mutex_lock (&atomic_mutex); 02509 res = atomic->value; 02510 atomic->value += 1; 02511 pthread_mutex_unlock (&atomic_mutex); 02512 02513 return res; 02514 #endif 02515 } 02516 02523 dbus_int32_t 02524 _dbus_atomic_dec (DBusAtomic *atomic) 02525 { 02526 #if DBUS_USE_SYNC 02527 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02528 #else 02529 dbus_int32_t res; 02530 02531 pthread_mutex_lock (&atomic_mutex); 02532 res = atomic->value; 02533 atomic->value -= 1; 02534 pthread_mutex_unlock (&atomic_mutex); 02535 02536 return res; 02537 #endif 02538 } 02539 02547 dbus_int32_t 02548 _dbus_atomic_get (DBusAtomic *atomic) 02549 { 02550 #if DBUS_USE_SYNC 02551 __sync_synchronize (); 02552 return atomic->value; 02553 #else 02554 dbus_int32_t res; 02555 02556 pthread_mutex_lock (&atomic_mutex); 02557 res = atomic->value; 02558 pthread_mutex_unlock (&atomic_mutex); 02559 02560 return res; 02561 #endif 02562 } 02563 02572 int 02573 _dbus_poll (DBusPollFD *fds, 02574 int n_fds, 02575 int timeout_milliseconds) 02576 { 02577 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02578 /* This big thing is a constant expression and should get optimized 02579 * out of existence. So it's more robust than a configure check at 02580 * no cost. 02581 */ 02582 if (_DBUS_POLLIN == POLLIN && 02583 _DBUS_POLLPRI == POLLPRI && 02584 _DBUS_POLLOUT == POLLOUT && 02585 _DBUS_POLLERR == POLLERR && 02586 _DBUS_POLLHUP == POLLHUP && 02587 _DBUS_POLLNVAL == POLLNVAL && 02588 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02589 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02590 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02591 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02592 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02593 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02594 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02595 { 02596 return poll ((struct pollfd*) fds, 02597 n_fds, 02598 timeout_milliseconds); 02599 } 02600 else 02601 { 02602 /* We have to convert the DBusPollFD to an array of 02603 * struct pollfd, poll, and convert back. 02604 */ 02605 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02606 return -1; 02607 } 02608 #else /* ! HAVE_POLL */ 02609 02610 fd_set read_set, write_set, err_set; 02611 int max_fd = 0; 02612 int i; 02613 struct timeval tv; 02614 int ready; 02615 02616 FD_ZERO (&read_set); 02617 FD_ZERO (&write_set); 02618 FD_ZERO (&err_set); 02619 02620 for (i = 0; i < n_fds; i++) 02621 { 02622 DBusPollFD *fdp = &fds[i]; 02623 02624 if (fdp->events & _DBUS_POLLIN) 02625 FD_SET (fdp->fd, &read_set); 02626 02627 if (fdp->events & _DBUS_POLLOUT) 02628 FD_SET (fdp->fd, &write_set); 02629 02630 FD_SET (fdp->fd, &err_set); 02631 02632 max_fd = MAX (max_fd, fdp->fd); 02633 } 02634 02635 tv.tv_sec = timeout_milliseconds / 1000; 02636 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02637 02638 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02639 timeout_milliseconds < 0 ? NULL : &tv); 02640 02641 if (ready > 0) 02642 { 02643 for (i = 0; i < n_fds; i++) 02644 { 02645 DBusPollFD *fdp = &fds[i]; 02646 02647 fdp->revents = 0; 02648 02649 if (FD_ISSET (fdp->fd, &read_set)) 02650 fdp->revents |= _DBUS_POLLIN; 02651 02652 if (FD_ISSET (fdp->fd, &write_set)) 02653 fdp->revents |= _DBUS_POLLOUT; 02654 02655 if (FD_ISSET (fdp->fd, &err_set)) 02656 fdp->revents |= _DBUS_POLLERR; 02657 } 02658 } 02659 02660 return ready; 02661 #endif 02662 } 02663 02671 void 02672 _dbus_get_monotonic_time (long *tv_sec, 02673 long *tv_usec) 02674 { 02675 #ifdef HAVE_MONOTONIC_CLOCK 02676 struct timespec ts; 02677 clock_gettime (CLOCK_MONOTONIC, &ts); 02678 02679 if (tv_sec) 02680 *tv_sec = ts.tv_sec; 02681 if (tv_usec) 02682 *tv_usec = ts.tv_nsec / 1000; 02683 #else 02684 struct timeval t; 02685 02686 gettimeofday (&t, NULL); 02687 02688 if (tv_sec) 02689 *tv_sec = t.tv_sec; 02690 if (tv_usec) 02691 *tv_usec = t.tv_usec; 02692 #endif 02693 } 02694 02702 void 02703 _dbus_get_real_time (long *tv_sec, 02704 long *tv_usec) 02705 { 02706 struct timeval t; 02707 02708 gettimeofday (&t, NULL); 02709 02710 if (tv_sec) 02711 *tv_sec = t.tv_sec; 02712 if (tv_usec) 02713 *tv_usec = t.tv_usec; 02714 } 02715 02724 dbus_bool_t 02725 _dbus_create_directory (const DBusString *filename, 02726 DBusError *error) 02727 { 02728 const char *filename_c; 02729 02730 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02731 02732 filename_c = _dbus_string_get_const_data (filename); 02733 02734 if (mkdir (filename_c, 0700) < 0) 02735 { 02736 if (errno == EEXIST) 02737 return TRUE; 02738 02739 dbus_set_error (error, DBUS_ERROR_FAILED, 02740 "Failed to create directory %s: %s\n", 02741 filename_c, _dbus_strerror (errno)); 02742 return FALSE; 02743 } 02744 else 02745 return TRUE; 02746 } 02747 02758 dbus_bool_t 02759 _dbus_concat_dir_and_file (DBusString *dir, 02760 const DBusString *next_component) 02761 { 02762 dbus_bool_t dir_ends_in_slash; 02763 dbus_bool_t file_starts_with_slash; 02764 02765 if (_dbus_string_get_length (dir) == 0 || 02766 _dbus_string_get_length (next_component) == 0) 02767 return TRUE; 02768 02769 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02770 _dbus_string_get_length (dir) - 1); 02771 02772 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02773 02774 if (dir_ends_in_slash && file_starts_with_slash) 02775 { 02776 _dbus_string_shorten (dir, 1); 02777 } 02778 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02779 { 02780 if (!_dbus_string_append_byte (dir, '/')) 02781 return FALSE; 02782 } 02783 02784 return _dbus_string_copy (next_component, 0, dir, 02785 _dbus_string_get_length (dir)); 02786 } 02787 02789 #define NANOSECONDS_PER_SECOND 1000000000 02790 02791 #define MICROSECONDS_PER_SECOND 1000000 02792 02793 #define MILLISECONDS_PER_SECOND 1000 02794 02795 #define NANOSECONDS_PER_MILLISECOND 1000000 02796 02797 #define MICROSECONDS_PER_MILLISECOND 1000 02798 02803 void 02804 _dbus_sleep_milliseconds (int milliseconds) 02805 { 02806 #ifdef HAVE_NANOSLEEP 02807 struct timespec req; 02808 struct timespec rem; 02809 02810 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02811 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02812 rem.tv_sec = 0; 02813 rem.tv_nsec = 0; 02814 02815 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02816 req = rem; 02817 #elif defined (HAVE_USLEEP) 02818 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02819 #else /* ! HAVE_USLEEP */ 02820 sleep (MAX (milliseconds / 1000, 1)); 02821 #endif 02822 } 02823 02824 static dbus_bool_t 02825 _dbus_generate_pseudorandom_bytes (DBusString *str, 02826 int n_bytes) 02827 { 02828 int old_len; 02829 char *p; 02830 02831 old_len = _dbus_string_get_length (str); 02832 02833 if (!_dbus_string_lengthen (str, n_bytes)) 02834 return FALSE; 02835 02836 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02837 02838 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02839 02840 return TRUE; 02841 } 02842 02851 dbus_bool_t 02852 _dbus_generate_random_bytes (DBusString *str, 02853 int n_bytes) 02854 { 02855 int old_len; 02856 int fd; 02857 02858 /* FALSE return means "no memory", if it could 02859 * mean something else then we'd need to return 02860 * a DBusError. So we always fall back to pseudorandom 02861 * if the I/O fails. 02862 */ 02863 02864 old_len = _dbus_string_get_length (str); 02865 fd = -1; 02866 02867 /* note, urandom on linux will fall back to pseudorandom */ 02868 fd = open ("/dev/urandom", O_RDONLY); 02869 if (fd < 0) 02870 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02871 02872 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02873 02874 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02875 { 02876 _dbus_close (fd, NULL); 02877 _dbus_string_set_length (str, old_len); 02878 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02879 } 02880 02881 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02882 n_bytes); 02883 02884 _dbus_close (fd, NULL); 02885 02886 return TRUE; 02887 } 02888 02894 void 02895 _dbus_exit (int code) 02896 { 02897 _exit (code); 02898 } 02899 02908 const char* 02909 _dbus_strerror (int error_number) 02910 { 02911 const char *msg; 02912 02913 msg = strerror (error_number); 02914 if (msg == NULL) 02915 msg = "unknown"; 02916 02917 return msg; 02918 } 02919 02923 void 02924 _dbus_disable_sigpipe (void) 02925 { 02926 signal (SIGPIPE, SIG_IGN); 02927 } 02928 02936 void 02937 _dbus_fd_set_close_on_exec (intptr_t fd) 02938 { 02939 int val; 02940 02941 val = fcntl (fd, F_GETFD, 0); 02942 02943 if (val < 0) 02944 return; 02945 02946 val |= FD_CLOEXEC; 02947 02948 fcntl (fd, F_SETFD, val); 02949 } 02950 02958 dbus_bool_t 02959 _dbus_close (int fd, 02960 DBusError *error) 02961 { 02962 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02963 02964 again: 02965 if (close (fd) < 0) 02966 { 02967 if (errno == EINTR) 02968 goto again; 02969 02970 dbus_set_error (error, _dbus_error_from_errno (errno), 02971 "Could not close fd %d", fd); 02972 return FALSE; 02973 } 02974 02975 return TRUE; 02976 } 02977 02986 int 02987 _dbus_dup(int fd, 02988 DBusError *error) 02989 { 02990 int new_fd; 02991 02992 #ifdef F_DUPFD_CLOEXEC 02993 dbus_bool_t cloexec_done; 02994 02995 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02996 cloexec_done = new_fd >= 0; 02997 02998 if (new_fd < 0 && errno == EINVAL) 02999 #endif 03000 { 03001 new_fd = fcntl(fd, F_DUPFD, 3); 03002 } 03003 03004 if (new_fd < 0) { 03005 03006 dbus_set_error (error, _dbus_error_from_errno (errno), 03007 "Could not duplicate fd %d", fd); 03008 return -1; 03009 } 03010 03011 #ifdef F_DUPFD_CLOEXEC 03012 if (!cloexec_done) 03013 #endif 03014 { 03015 _dbus_fd_set_close_on_exec(new_fd); 03016 } 03017 03018 return new_fd; 03019 } 03020 03028 dbus_bool_t 03029 _dbus_set_fd_nonblocking (int fd, 03030 DBusError *error) 03031 { 03032 int val; 03033 03034 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03035 03036 val = fcntl (fd, F_GETFL, 0); 03037 if (val < 0) 03038 { 03039 dbus_set_error (error, _dbus_error_from_errno (errno), 03040 "Failed to get flags from file descriptor %d: %s", 03041 fd, _dbus_strerror (errno)); 03042 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 03043 _dbus_strerror (errno)); 03044 return FALSE; 03045 } 03046 03047 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 03048 { 03049 dbus_set_error (error, _dbus_error_from_errno (errno), 03050 "Failed to set nonblocking flag of file descriptor %d: %s", 03051 fd, _dbus_strerror (errno)); 03052 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 03053 fd, _dbus_strerror (errno)); 03054 03055 return FALSE; 03056 } 03057 03058 return TRUE; 03059 } 03060 03066 void 03067 _dbus_print_backtrace (void) 03068 { 03069 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 03070 void *bt[500]; 03071 int bt_size; 03072 int i; 03073 char **syms; 03074 03075 bt_size = backtrace (bt, 500); 03076 03077 syms = backtrace_symbols (bt, bt_size); 03078 03079 i = 0; 03080 while (i < bt_size) 03081 { 03082 /* don't use dbus_warn since it can _dbus_abort() */ 03083 fprintf (stderr, " %s\n", syms[i]); 03084 ++i; 03085 } 03086 fflush (stderr); 03087 03088 free (syms); 03089 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 03090 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 03091 #else 03092 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 03093 #endif 03094 } 03095 03108 dbus_bool_t 03109 _dbus_full_duplex_pipe (int *fd1, 03110 int *fd2, 03111 dbus_bool_t blocking, 03112 DBusError *error) 03113 { 03114 #ifdef HAVE_SOCKETPAIR 03115 int fds[2]; 03116 int retval; 03117 03118 #ifdef SOCK_CLOEXEC 03119 dbus_bool_t cloexec_done; 03120 03121 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 03122 cloexec_done = retval >= 0; 03123 03124 if (retval < 0 && (errno == EINVAL || errno == EPROTOTYPE)) 03125 #endif 03126 { 03127 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 03128 } 03129 03130 if (retval < 0) 03131 { 03132 dbus_set_error (error, _dbus_error_from_errno (errno), 03133 "Could not create full-duplex pipe"); 03134 return FALSE; 03135 } 03136 03137 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03138 03139 #ifdef SOCK_CLOEXEC 03140 if (!cloexec_done) 03141 #endif 03142 { 03143 _dbus_fd_set_close_on_exec (fds[0]); 03144 _dbus_fd_set_close_on_exec (fds[1]); 03145 } 03146 03147 if (!blocking && 03148 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 03149 !_dbus_set_fd_nonblocking (fds[1], NULL))) 03150 { 03151 dbus_set_error (error, _dbus_error_from_errno (errno), 03152 "Could not set full-duplex pipe nonblocking"); 03153 03154 _dbus_close (fds[0], NULL); 03155 _dbus_close (fds[1], NULL); 03156 03157 return FALSE; 03158 } 03159 03160 *fd1 = fds[0]; 03161 *fd2 = fds[1]; 03162 03163 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 03164 *fd1, *fd2); 03165 03166 return TRUE; 03167 #else 03168 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 03169 dbus_set_error (error, DBUS_ERROR_FAILED, 03170 "_dbus_full_duplex_pipe() not implemented on this OS"); 03171 return FALSE; 03172 #endif 03173 } 03174 03183 int 03184 _dbus_printf_string_upper_bound (const char *format, 03185 va_list args) 03186 { 03187 char static_buf[1024]; 03188 int bufsize = sizeof (static_buf); 03189 int len; 03190 va_list args_copy; 03191 03192 DBUS_VA_COPY (args_copy, args); 03193 len = vsnprintf (static_buf, bufsize, format, args_copy); 03194 va_end (args_copy); 03195 03196 /* If vsnprintf() returned non-negative, then either the string fits in 03197 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03198 * returns the number of characters that were needed, or this OS returns the 03199 * truncated length. 03200 * 03201 * We ignore the possibility that snprintf might just ignore the length and 03202 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03203 * If your libc is really that bad, come back when you have a better one. */ 03204 if (len == bufsize) 03205 { 03206 /* This could be the truncated length (Tru64 and IRIX have this bug), 03207 * or the real length could be coincidentally the same. Which is it? 03208 * If vsnprintf returns the truncated length, we'll go to the slow 03209 * path. */ 03210 DBUS_VA_COPY (args_copy, args); 03211 03212 if (vsnprintf (static_buf, 1, format, args_copy) == 1) 03213 len = -1; 03214 03215 va_end (args_copy); 03216 } 03217 03218 /* If vsnprintf() returned negative, we have to do more work. 03219 * HP-UX returns negative. */ 03220 while (len < 0) 03221 { 03222 char *buf; 03223 03224 bufsize *= 2; 03225 03226 buf = dbus_malloc (bufsize); 03227 03228 if (buf == NULL) 03229 return -1; 03230 03231 DBUS_VA_COPY (args_copy, args); 03232 len = vsnprintf (buf, bufsize, format, args_copy); 03233 va_end (args_copy); 03234 03235 dbus_free (buf); 03236 03237 /* If the reported length is exactly the buffer size, round up to the 03238 * next size, in case vsnprintf has been returning the truncated 03239 * length */ 03240 if (len == bufsize) 03241 len = -1; 03242 } 03243 03244 return len; 03245 } 03246 03253 const char* 03254 _dbus_get_tmpdir(void) 03255 { 03256 /* Protected by _DBUS_LOCK_sysdeps */ 03257 static const char* tmpdir = NULL; 03258 03259 if (!_DBUS_LOCK (sysdeps)) 03260 return NULL; 03261 03262 if (tmpdir == NULL) 03263 { 03264 /* TMPDIR is what glibc uses, then 03265 * glibc falls back to the P_tmpdir macro which 03266 * just expands to "/tmp" 03267 */ 03268 if (tmpdir == NULL) 03269 tmpdir = getenv("TMPDIR"); 03270 03271 /* These two env variables are probably 03272 * broken, but maybe some OS uses them? 03273 */ 03274 if (tmpdir == NULL) 03275 tmpdir = getenv("TMP"); 03276 if (tmpdir == NULL) 03277 tmpdir = getenv("TEMP"); 03278 03279 /* And this is the sane fallback. */ 03280 if (tmpdir == NULL) 03281 tmpdir = "/tmp"; 03282 } 03283 03284 _DBUS_UNLOCK (sysdeps); 03285 03286 _dbus_assert(tmpdir != NULL); 03287 03288 return tmpdir; 03289 } 03290 03291 #if defined(DBUS_ENABLE_X11_AUTOLAUNCH) || defined(DBUS_ENABLE_LAUNCHD) 03292 03311 static dbus_bool_t 03312 _read_subprocess_line_argv (const char *progpath, 03313 dbus_bool_t path_fallback, 03314 char * const *argv, 03315 DBusString *result, 03316 DBusError *error) 03317 { 03318 int result_pipe[2] = { -1, -1 }; 03319 int errors_pipe[2] = { -1, -1 }; 03320 pid_t pid; 03321 int ret; 03322 int status; 03323 int orig_len; 03324 03325 dbus_bool_t retval; 03326 sigset_t new_set, old_set; 03327 03328 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03329 retval = FALSE; 03330 03331 /* We need to block any existing handlers for SIGCHLD temporarily; they 03332 * will cause waitpid() below to fail. 03333 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03334 */ 03335 sigemptyset (&new_set); 03336 sigaddset (&new_set, SIGCHLD); 03337 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03338 03339 orig_len = _dbus_string_get_length (result); 03340 03341 #define READ_END 0 03342 #define WRITE_END 1 03343 if (pipe (result_pipe) < 0) 03344 { 03345 dbus_set_error (error, _dbus_error_from_errno (errno), 03346 "Failed to create a pipe to call %s: %s", 03347 progpath, _dbus_strerror (errno)); 03348 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03349 progpath, _dbus_strerror (errno)); 03350 goto out; 03351 } 03352 if (pipe (errors_pipe) < 0) 03353 { 03354 dbus_set_error (error, _dbus_error_from_errno (errno), 03355 "Failed to create a pipe to call %s: %s", 03356 progpath, _dbus_strerror (errno)); 03357 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03358 progpath, _dbus_strerror (errno)); 03359 goto out; 03360 } 03361 03362 pid = fork (); 03363 if (pid < 0) 03364 { 03365 dbus_set_error (error, _dbus_error_from_errno (errno), 03366 "Failed to fork() to call %s: %s", 03367 progpath, _dbus_strerror (errno)); 03368 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03369 progpath, _dbus_strerror (errno)); 03370 goto out; 03371 } 03372 03373 if (pid == 0) 03374 { 03375 /* child process */ 03376 int fd; 03377 03378 fd = open ("/dev/null", O_RDWR); 03379 if (fd == -1) 03380 /* huh?! can't open /dev/null? */ 03381 _exit (1); 03382 03383 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03384 03385 /* set-up stdXXX */ 03386 close (result_pipe[READ_END]); 03387 close (errors_pipe[READ_END]); 03388 03389 if (dup2 (fd, 0) == -1) /* setup stdin */ 03390 _exit (1); 03391 if (dup2 (result_pipe[WRITE_END], 1) == -1) /* setup stdout */ 03392 _exit (1); 03393 if (dup2 (errors_pipe[WRITE_END], 2) == -1) /* setup stderr */ 03394 _exit (1); 03395 03396 _dbus_close_all (); 03397 03398 sigprocmask (SIG_SETMASK, &old_set, NULL); 03399 03400 /* If it looks fully-qualified, try execv first */ 03401 if (progpath[0] == '/') 03402 { 03403 execv (progpath, argv); 03404 /* Ok, that failed. Now if path_fallback is given, let's 03405 * try unqualified. This is mostly a hack to work 03406 * around systems which ship dbus-launch in /usr/bin 03407 * but everything else in /bin (because dbus-launch 03408 * depends on X11). 03409 */ 03410 if (path_fallback) 03411 /* We must have a slash, because we checked above */ 03412 execvp (strrchr (progpath, '/')+1, argv); 03413 } 03414 else 03415 execvp (progpath, argv); 03416 03417 /* still nothing, we failed */ 03418 _exit (1); 03419 } 03420 03421 /* parent process */ 03422 close (result_pipe[WRITE_END]); 03423 close (errors_pipe[WRITE_END]); 03424 result_pipe[WRITE_END] = -1; 03425 errors_pipe[WRITE_END] = -1; 03426 03427 ret = 0; 03428 do 03429 { 03430 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03431 } 03432 while (ret > 0); 03433 03434 /* reap the child process to avoid it lingering as zombie */ 03435 do 03436 { 03437 ret = waitpid (pid, &status, 0); 03438 } 03439 while (ret == -1 && errno == EINTR); 03440 03441 /* We succeeded if the process exited with status 0 and 03442 anything was read */ 03443 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03444 { 03445 /* The process ended with error */ 03446 DBusString error_message; 03447 if (!_dbus_string_init (&error_message)) 03448 { 03449 _DBUS_SET_OOM (error); 03450 goto out; 03451 } 03452 03453 ret = 0; 03454 do 03455 { 03456 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03457 } 03458 while (ret > 0); 03459 03460 _dbus_string_set_length (result, orig_len); 03461 if (_dbus_string_get_length (&error_message) > 0) 03462 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03463 "%s terminated abnormally with the following error: %s", 03464 progpath, _dbus_string_get_data (&error_message)); 03465 else 03466 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03467 "%s terminated abnormally without any error message", 03468 progpath); 03469 goto out; 03470 } 03471 03472 retval = TRUE; 03473 03474 out: 03475 sigprocmask (SIG_SETMASK, &old_set, NULL); 03476 03477 if (retval) 03478 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03479 else 03480 _DBUS_ASSERT_ERROR_IS_SET (error); 03481 03482 if (result_pipe[0] != -1) 03483 close (result_pipe[0]); 03484 if (result_pipe[1] != -1) 03485 close (result_pipe[1]); 03486 if (errors_pipe[0] != -1) 03487 close (errors_pipe[0]); 03488 if (errors_pipe[1] != -1) 03489 close (errors_pipe[1]); 03490 03491 return retval; 03492 } 03493 #endif 03494 03507 dbus_bool_t 03508 _dbus_get_autolaunch_address (const char *scope, 03509 DBusString *address, 03510 DBusError *error) 03511 { 03512 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03513 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03514 * but that's done elsewhere, and if it worked, this function wouldn't 03515 * be called.) */ 03516 const char *display; 03517 char *argv[6]; 03518 int i; 03519 DBusString uuid; 03520 dbus_bool_t retval; 03521 03522 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03523 retval = FALSE; 03524 03525 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03526 * dbus-launch-x11 is just going to fail. Rather than trying to 03527 * run it, we might as well bail out early with a nice error. */ 03528 display = _dbus_getenv ("DISPLAY"); 03529 03530 if (display == NULL || display[0] == '\0') 03531 { 03532 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03533 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03534 return FALSE; 03535 } 03536 03537 if (!_dbus_string_init (&uuid)) 03538 { 03539 _DBUS_SET_OOM (error); 03540 return FALSE; 03541 } 03542 03543 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03544 { 03545 _DBUS_SET_OOM (error); 03546 goto out; 03547 } 03548 03549 i = 0; 03550 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 03551 if (_dbus_getenv ("DBUS_USE_TEST_BINARY") != NULL) 03552 argv[i] = TEST_BUS_LAUNCH_BINARY; 03553 else 03554 #endif 03555 argv[i] = DBUS_BINDIR "/dbus-launch"; 03556 ++i; 03557 argv[i] = "--autolaunch"; 03558 ++i; 03559 argv[i] = _dbus_string_get_data (&uuid); 03560 ++i; 03561 argv[i] = "--binary-syntax"; 03562 ++i; 03563 argv[i] = "--close-stderr"; 03564 ++i; 03565 argv[i] = NULL; 03566 ++i; 03567 03568 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03569 03570 retval = _read_subprocess_line_argv (argv[0], 03571 TRUE, 03572 argv, address, error); 03573 03574 out: 03575 _dbus_string_free (&uuid); 03576 return retval; 03577 #else 03578 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03579 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03580 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03581 return FALSE; 03582 #endif 03583 } 03584 03603 dbus_bool_t 03604 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03605 dbus_bool_t create_if_not_found, 03606 DBusError *error) 03607 { 03608 DBusString filename; 03609 dbus_bool_t b; 03610 03611 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03612 03613 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03614 if (b) 03615 return TRUE; 03616 03617 dbus_error_free (error); 03618 03619 /* Fallback to the system machine ID */ 03620 _dbus_string_init_const (&filename, "/etc/machine-id"); 03621 b = _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03622 03623 if (b) 03624 { 03625 /* try to copy it to the DBUS_MACHINE_UUID_FILE, but do not 03626 * complain if that isn't possible for whatever reason */ 03627 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03628 _dbus_write_uuid_file (&filename, machine_id, NULL); 03629 03630 return TRUE; 03631 } 03632 03633 if (!create_if_not_found) 03634 return FALSE; 03635 03636 /* if none found, try to make a new one */ 03637 dbus_error_free (error); 03638 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03639 _dbus_generate_uuid (machine_id); 03640 return _dbus_write_uuid_file (&filename, machine_id, error); 03641 } 03642 03650 dbus_bool_t 03651 _dbus_lookup_launchd_socket (DBusString *socket_path, 03652 const char *launchd_env_var, 03653 DBusError *error) 03654 { 03655 #ifdef DBUS_ENABLE_LAUNCHD 03656 char *argv[4]; 03657 int i; 03658 03659 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03660 03661 i = 0; 03662 argv[i] = "launchctl"; 03663 ++i; 03664 argv[i] = "getenv"; 03665 ++i; 03666 argv[i] = (char*)launchd_env_var; 03667 ++i; 03668 argv[i] = NULL; 03669 ++i; 03670 03671 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03672 03673 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03674 { 03675 return FALSE; 03676 } 03677 03678 /* no error, but no result either */ 03679 if (_dbus_string_get_length(socket_path) == 0) 03680 { 03681 return FALSE; 03682 } 03683 03684 /* strip the carriage-return */ 03685 _dbus_string_shorten(socket_path, 1); 03686 return TRUE; 03687 #else /* DBUS_ENABLE_LAUNCHD */ 03688 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03689 "can't lookup socket from launchd; launchd support not compiled in"); 03690 return FALSE; 03691 #endif 03692 } 03693 03694 #ifdef DBUS_ENABLE_LAUNCHD 03695 static dbus_bool_t 03696 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03697 { 03698 dbus_bool_t valid_socket; 03699 DBusString socket_path; 03700 03701 if (!_dbus_string_init (&socket_path)) 03702 { 03703 _DBUS_SET_OOM (error); 03704 return FALSE; 03705 } 03706 03707 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03708 03709 if (dbus_error_is_set(error)) 03710 { 03711 _dbus_string_free(&socket_path); 03712 return FALSE; 03713 } 03714 03715 if (!valid_socket) 03716 { 03717 dbus_set_error(error, "no socket path", 03718 "launchd did not provide a socket path, " 03719 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03720 _dbus_string_free(&socket_path); 03721 return FALSE; 03722 } 03723 if (!_dbus_string_append (address, "unix:path=")) 03724 { 03725 _DBUS_SET_OOM (error); 03726 _dbus_string_free(&socket_path); 03727 return FALSE; 03728 } 03729 if (!_dbus_string_copy (&socket_path, 0, address, 03730 _dbus_string_get_length (address))) 03731 { 03732 _DBUS_SET_OOM (error); 03733 _dbus_string_free(&socket_path); 03734 return FALSE; 03735 } 03736 03737 _dbus_string_free(&socket_path); 03738 return TRUE; 03739 } 03740 #endif 03741 03761 dbus_bool_t 03762 _dbus_lookup_session_address (dbus_bool_t *supported, 03763 DBusString *address, 03764 DBusError *error) 03765 { 03766 #ifdef DBUS_ENABLE_LAUNCHD 03767 *supported = TRUE; 03768 return _dbus_lookup_session_address_launchd (address, error); 03769 #else 03770 /* On non-Mac Unix platforms, if the session address isn't already 03771 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03772 * fall back to the autolaunch: global default; see 03773 * init_session_address in dbus/dbus-bus.c. */ 03774 *supported = FALSE; 03775 return TRUE; 03776 #endif 03777 } 03778 03786 void 03787 _dbus_flush_caches (void) 03788 { 03789 _dbus_user_database_flush_system (); 03790 } 03791 03805 dbus_bool_t 03806 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03807 DBusCredentials *credentials) 03808 { 03809 DBusString homedir; 03810 DBusString dotdir; 03811 dbus_uid_t uid; 03812 03813 _dbus_assert (credentials != NULL); 03814 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03815 03816 if (!_dbus_string_init (&homedir)) 03817 return FALSE; 03818 03819 uid = _dbus_credentials_get_unix_uid (credentials); 03820 _dbus_assert (uid != DBUS_UID_UNSET); 03821 03822 if (!_dbus_homedir_from_uid (uid, &homedir)) 03823 goto failed; 03824 03825 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 03826 { 03827 const char *override; 03828 03829 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03830 if (override != NULL && *override != '\0') 03831 { 03832 _dbus_string_set_length (&homedir, 0); 03833 if (!_dbus_string_append (&homedir, override)) 03834 goto failed; 03835 03836 _dbus_verbose ("Using fake homedir for testing: %s\n", 03837 _dbus_string_get_const_data (&homedir)); 03838 } 03839 else 03840 { 03841 /* Not strictly thread-safe, but if we fail at thread-safety here, 03842 * the worst that will happen is some extra warnings. */ 03843 static dbus_bool_t already_warned = FALSE; 03844 if (!already_warned) 03845 { 03846 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03847 already_warned = TRUE; 03848 } 03849 } 03850 } 03851 #endif 03852 03853 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03854 if (!_dbus_concat_dir_and_file (&homedir, 03855 &dotdir)) 03856 goto failed; 03857 03858 if (!_dbus_string_copy (&homedir, 0, 03859 directory, _dbus_string_get_length (directory))) { 03860 goto failed; 03861 } 03862 03863 _dbus_string_free (&homedir); 03864 return TRUE; 03865 03866 failed: 03867 _dbus_string_free (&homedir); 03868 return FALSE; 03869 } 03870 03871 //PENDING(kdab) docs 03872 dbus_bool_t 03873 _dbus_daemon_publish_session_bus_address (const char* addr, 03874 const char *scope) 03875 { 03876 return TRUE; 03877 } 03878 03879 //PENDING(kdab) docs 03880 void 03881 _dbus_daemon_unpublish_session_bus_address (void) 03882 { 03883 03884 } 03885 03892 dbus_bool_t 03893 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03894 { 03895 return errno == EAGAIN || errno == EWOULDBLOCK; 03896 } 03897 03905 dbus_bool_t 03906 _dbus_delete_directory (const DBusString *filename, 03907 DBusError *error) 03908 { 03909 const char *filename_c; 03910 03911 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03912 03913 filename_c = _dbus_string_get_const_data (filename); 03914 03915 if (rmdir (filename_c) != 0) 03916 { 03917 dbus_set_error (error, DBUS_ERROR_FAILED, 03918 "Failed to remove directory %s: %s\n", 03919 filename_c, _dbus_strerror (errno)); 03920 return FALSE; 03921 } 03922 03923 return TRUE; 03924 } 03925 03933 dbus_bool_t 03934 _dbus_socket_can_pass_unix_fd(int fd) { 03935 03936 #ifdef SCM_RIGHTS 03937 union { 03938 struct sockaddr sa; 03939 struct sockaddr_storage storage; 03940 struct sockaddr_un un; 03941 } sa_buf; 03942 03943 socklen_t sa_len = sizeof(sa_buf); 03944 03945 _DBUS_ZERO(sa_buf); 03946 03947 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 03948 return FALSE; 03949 03950 return sa_buf.sa.sa_family == AF_UNIX; 03951 03952 #else 03953 return FALSE; 03954 03955 #endif 03956 } 03957 03962 void 03963 _dbus_close_all (void) 03964 { 03965 int maxfds, i; 03966 03967 #if HAVE_CLOSEFROM 03968 closefrom(3); 03969 #endif 03970 03971 #ifdef __linux__ 03972 DIR *d; 03973 03974 /* On Linux we can optimize this a bit if /proc is available. If it 03975 isn't available, fall back to the brute force way. */ 03976 03977 d = opendir ("/proc/self/fd"); 03978 if (d) 03979 { 03980 for (;;) 03981 { 03982 struct dirent buf, *de; 03983 int k, fd; 03984 long l; 03985 char *e = NULL; 03986 03987 k = readdir_r (d, &buf, &de); 03988 if (k != 0 || !de) 03989 break; 03990 03991 if (de->d_name[0] == '.') 03992 continue; 03993 03994 errno = 0; 03995 l = strtol (de->d_name, &e, 10); 03996 if (errno != 0 || e == NULL || *e != '\0') 03997 continue; 03998 03999 fd = (int) l; 04000 if (fd < 3) 04001 continue; 04002 04003 if (fd == dirfd (d)) 04004 continue; 04005 04006 close (fd); 04007 } 04008 04009 closedir (d); 04010 return; 04011 } 04012 #endif 04013 04014 maxfds = sysconf (_SC_OPEN_MAX); 04015 04016 /* Pick something reasonable if for some reason sysconf says 04017 * unlimited. 04018 */ 04019 if (maxfds < 0) 04020 maxfds = 1024; 04021 04022 /* close all inherited fds */ 04023 for (i = 3; i < maxfds; i++) 04024 close (i); 04025 } 04026 04034 dbus_bool_t 04035 _dbus_append_address_from_socket (int fd, 04036 DBusString *address, 04037 DBusError *error) 04038 { 04039 union { 04040 struct sockaddr sa; 04041 struct sockaddr_storage storage; 04042 struct sockaddr_un un; 04043 struct sockaddr_in ipv4; 04044 struct sockaddr_in6 ipv6; 04045 } socket; 04046 char hostip[INET6_ADDRSTRLEN]; 04047 int size = sizeof (socket); 04048 DBusString path_str; 04049 04050 if (getsockname (fd, &socket.sa, &size)) 04051 goto err; 04052 04053 switch (socket.sa.sa_family) 04054 { 04055 case AF_UNIX: 04056 if (socket.un.sun_path[0]=='\0') 04057 { 04058 _dbus_string_init_const (&path_str, &(socket.un.sun_path[1])); 04059 if (_dbus_string_append (address, "unix:abstract=") && 04060 _dbus_address_append_escaped (address, &path_str)) 04061 return TRUE; 04062 } 04063 else 04064 { 04065 _dbus_string_init_const (&path_str, socket.un.sun_path); 04066 if (_dbus_string_append (address, "unix:path=") && 04067 _dbus_address_append_escaped (address, &path_str)) 04068 return TRUE; 04069 } 04070 break; 04071 case AF_INET: 04072 if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip))) 04073 if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u", 04074 hostip, ntohs (socket.ipv4.sin_port))) 04075 return TRUE; 04076 break; 04077 #ifdef AF_INET6 04078 case AF_INET6: 04079 _dbus_string_init_const (&path_str, hostip); 04080 if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip))) 04081 if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=", 04082 ntohs (socket.ipv6.sin6_port)) && 04083 _dbus_address_append_escaped (address, &path_str)) 04084 return TRUE; 04085 break; 04086 #endif 04087 default: 04088 dbus_set_error (error, 04089 _dbus_error_from_errno (EINVAL), 04090 "Failed to read address from socket: Unknown socket type."); 04091 return FALSE; 04092 } 04093 err: 04094 dbus_set_error (error, 04095 _dbus_error_from_errno (errno), 04096 "Failed to open socket: %s", 04097 _dbus_strerror (errno)); 04098 return FALSE; 04099 } 04100 04101 /* tests in dbus-sysdeps-util.c */
1.7.6.1