D-Bus
1.6.8
|
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 00059 #ifdef HAVE_ERRNO_H 00060 #include <errno.h> 00061 #endif 00062 #ifdef HAVE_WRITEV 00063 #include <sys/uio.h> 00064 #endif 00065 #ifdef HAVE_POLL 00066 #include <sys/poll.h> 00067 #endif 00068 #ifdef HAVE_BACKTRACE 00069 #include <execinfo.h> 00070 #endif 00071 #ifdef HAVE_GETPEERUCRED 00072 #include <ucred.h> 00073 #endif 00074 00075 #ifdef HAVE_ADT 00076 #include <bsm/adt.h> 00077 #endif 00078 00079 #include "sd-daemon.h" 00080 00081 #ifndef O_BINARY 00082 #define O_BINARY 0 00083 #endif 00084 00085 #ifndef AI_ADDRCONFIG 00086 #define AI_ADDRCONFIG 0 00087 #endif 00088 00089 #ifndef HAVE_SOCKLEN_T 00090 #define socklen_t int 00091 #endif 00092 00093 #if defined (__sun) || defined (__sun__) 00094 /* 00095 * CMS_SPACE etc. definitions for Solaris < 10, based on 00096 * http://mailman.videolan.org/pipermail/vlc-devel/2006-May/024402.html 00097 * via 00098 * http://wiki.opencsw.org/porting-faq#toc10 00099 * 00100 * These are only redefined for Solaris, for now: if your OS needs these too, 00101 * please file a bug. (Or preferably, improve your OS so they're not needed.) 00102 */ 00103 00104 # ifndef CMSG_ALIGN 00105 # ifdef __sun__ 00106 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN (len) 00107 # else 00108 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */ 00109 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & \ 00110 ~(sizeof (long) - 1)) 00111 # endif 00112 # endif 00113 00114 # ifndef CMSG_SPACE 00115 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + \ 00116 CMSG_ALIGN (len)) 00117 # endif 00118 00119 # ifndef CMSG_LEN 00120 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) 00121 # endif 00122 00123 #endif /* Solaris */ 00124 00125 static dbus_bool_t 00126 _dbus_open_socket (int *fd_p, 00127 int domain, 00128 int type, 00129 int protocol, 00130 DBusError *error) 00131 { 00132 #ifdef SOCK_CLOEXEC 00133 dbus_bool_t cloexec_done; 00134 00135 *fd_p = socket (domain, type | SOCK_CLOEXEC, protocol); 00136 cloexec_done = *fd_p >= 0; 00137 00138 /* Check if kernel seems to be too old to know SOCK_CLOEXEC */ 00139 if (*fd_p < 0 && errno == EINVAL) 00140 #endif 00141 { 00142 *fd_p = socket (domain, type, protocol); 00143 } 00144 00145 if (*fd_p >= 0) 00146 { 00147 #ifdef SOCK_CLOEXEC 00148 if (!cloexec_done) 00149 #endif 00150 { 00151 _dbus_fd_set_close_on_exec(*fd_p); 00152 } 00153 00154 _dbus_verbose ("socket fd %d opened\n", *fd_p); 00155 return TRUE; 00156 } 00157 else 00158 { 00159 dbus_set_error(error, 00160 _dbus_error_from_errno (errno), 00161 "Failed to open socket: %s", 00162 _dbus_strerror (errno)); 00163 return FALSE; 00164 } 00165 } 00166 00177 static dbus_bool_t 00178 _dbus_open_unix_socket (int *fd, 00179 DBusError *error) 00180 { 00181 return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error); 00182 } 00183 00192 dbus_bool_t 00193 _dbus_close_socket (int fd, 00194 DBusError *error) 00195 { 00196 return _dbus_close (fd, error); 00197 } 00198 00208 int 00209 _dbus_read_socket (int fd, 00210 DBusString *buffer, 00211 int count) 00212 { 00213 return _dbus_read (fd, buffer, count); 00214 } 00215 00226 int 00227 _dbus_write_socket (int fd, 00228 const DBusString *buffer, 00229 int start, 00230 int len) 00231 { 00232 #if HAVE_DECL_MSG_NOSIGNAL 00233 const char *data; 00234 int bytes_written; 00235 00236 data = _dbus_string_get_const_data_len (buffer, start, len); 00237 00238 again: 00239 00240 bytes_written = send (fd, data, len, MSG_NOSIGNAL); 00241 00242 if (bytes_written < 0 && errno == EINTR) 00243 goto again; 00244 00245 return bytes_written; 00246 00247 #else 00248 return _dbus_write (fd, buffer, start, len); 00249 #endif 00250 } 00251 00264 int 00265 _dbus_read_socket_with_unix_fds (int fd, 00266 DBusString *buffer, 00267 int count, 00268 int *fds, 00269 int *n_fds) { 00270 #ifndef HAVE_UNIX_FD_PASSING 00271 int r; 00272 00273 if ((r = _dbus_read_socket(fd, buffer, count)) < 0) 00274 return r; 00275 00276 *n_fds = 0; 00277 return r; 00278 00279 #else 00280 int bytes_read; 00281 int start; 00282 struct msghdr m; 00283 struct iovec iov; 00284 00285 _dbus_assert (count >= 0); 00286 _dbus_assert (*n_fds >= 0); 00287 00288 start = _dbus_string_get_length (buffer); 00289 00290 if (!_dbus_string_lengthen (buffer, count)) 00291 { 00292 errno = ENOMEM; 00293 return -1; 00294 } 00295 00296 _DBUS_ZERO(iov); 00297 iov.iov_base = _dbus_string_get_data_len (buffer, start, count); 00298 iov.iov_len = count; 00299 00300 _DBUS_ZERO(m); 00301 m.msg_iov = &iov; 00302 m.msg_iovlen = 1; 00303 00304 /* Hmm, we have no clue how long the control data will actually be 00305 that is queued for us. The least we can do is assume that the 00306 caller knows. Hence let's make space for the number of fds that 00307 we shall read at max plus the cmsg header. */ 00308 m.msg_controllen = CMSG_SPACE(*n_fds * sizeof(int)); 00309 00310 /* It's probably safe to assume that systems with SCM_RIGHTS also 00311 know alloca() */ 00312 m.msg_control = alloca(m.msg_controllen); 00313 memset(m.msg_control, 0, m.msg_controllen); 00314 00315 again: 00316 00317 bytes_read = recvmsg(fd, &m, 0 00318 #ifdef MSG_CMSG_CLOEXEC 00319 |MSG_CMSG_CLOEXEC 00320 #endif 00321 ); 00322 00323 if (bytes_read < 0) 00324 { 00325 if (errno == EINTR) 00326 goto again; 00327 else 00328 { 00329 /* put length back (note that this doesn't actually realloc anything) */ 00330 _dbus_string_set_length (buffer, start); 00331 return -1; 00332 } 00333 } 00334 else 00335 { 00336 struct cmsghdr *cm; 00337 dbus_bool_t found = FALSE; 00338 00339 if (m.msg_flags & MSG_CTRUNC) 00340 { 00341 /* Hmm, apparently the control data was truncated. The bad 00342 thing is that we might have completely lost a couple of fds 00343 without chance to recover them. Hence let's treat this as a 00344 serious error. */ 00345 00346 errno = ENOSPC; 00347 _dbus_string_set_length (buffer, start); 00348 return -1; 00349 } 00350 00351 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) 00352 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) 00353 { 00354 unsigned i; 00355 00356 _dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int))); 00357 *n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int); 00358 00359 memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int)); 00360 found = TRUE; 00361 00362 /* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually 00363 worked, hence we need to go through this list and set 00364 CLOEXEC everywhere in any case */ 00365 for (i = 0; i < *n_fds; i++) 00366 _dbus_fd_set_close_on_exec(fds[i]); 00367 00368 break; 00369 } 00370 00371 if (!found) 00372 *n_fds = 0; 00373 00374 /* put length back (doesn't actually realloc) */ 00375 _dbus_string_set_length (buffer, start + bytes_read); 00376 00377 #if 0 00378 if (bytes_read > 0) 00379 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00380 #endif 00381 00382 return bytes_read; 00383 } 00384 #endif 00385 } 00386 00387 int 00388 _dbus_write_socket_with_unix_fds(int fd, 00389 const DBusString *buffer, 00390 int start, 00391 int len, 00392 const int *fds, 00393 int n_fds) { 00394 00395 #ifndef HAVE_UNIX_FD_PASSING 00396 00397 if (n_fds > 0) { 00398 errno = ENOTSUP; 00399 return -1; 00400 } 00401 00402 return _dbus_write_socket(fd, buffer, start, len); 00403 #else 00404 return _dbus_write_socket_with_unix_fds_two(fd, buffer, start, len, NULL, 0, 0, fds, n_fds); 00405 #endif 00406 } 00407 00408 int 00409 _dbus_write_socket_with_unix_fds_two(int fd, 00410 const DBusString *buffer1, 00411 int start1, 00412 int len1, 00413 const DBusString *buffer2, 00414 int start2, 00415 int len2, 00416 const int *fds, 00417 int n_fds) { 00418 00419 #ifndef HAVE_UNIX_FD_PASSING 00420 00421 if (n_fds > 0) { 00422 errno = ENOTSUP; 00423 return -1; 00424 } 00425 00426 return _dbus_write_socket_two(fd, 00427 buffer1, start1, len1, 00428 buffer2, start2, len2); 00429 #else 00430 00431 struct msghdr m; 00432 struct cmsghdr *cm; 00433 struct iovec iov[2]; 00434 int bytes_written; 00435 00436 _dbus_assert (len1 >= 0); 00437 _dbus_assert (len2 >= 0); 00438 _dbus_assert (n_fds >= 0); 00439 00440 _DBUS_ZERO(iov); 00441 iov[0].iov_base = (char*) _dbus_string_get_const_data_len (buffer1, start1, len1); 00442 iov[0].iov_len = len1; 00443 00444 if (buffer2) 00445 { 00446 iov[1].iov_base = (char*) _dbus_string_get_const_data_len (buffer2, start2, len2); 00447 iov[1].iov_len = len2; 00448 } 00449 00450 _DBUS_ZERO(m); 00451 m.msg_iov = iov; 00452 m.msg_iovlen = buffer2 ? 2 : 1; 00453 00454 if (n_fds > 0) 00455 { 00456 m.msg_controllen = CMSG_SPACE(n_fds * sizeof(int)); 00457 m.msg_control = alloca(m.msg_controllen); 00458 memset(m.msg_control, 0, m.msg_controllen); 00459 00460 cm = CMSG_FIRSTHDR(&m); 00461 cm->cmsg_level = SOL_SOCKET; 00462 cm->cmsg_type = SCM_RIGHTS; 00463 cm->cmsg_len = CMSG_LEN(n_fds * sizeof(int)); 00464 memcpy(CMSG_DATA(cm), fds, n_fds * sizeof(int)); 00465 } 00466 00467 again: 00468 00469 bytes_written = sendmsg (fd, &m, 0 00470 #if HAVE_DECL_MSG_NOSIGNAL 00471 |MSG_NOSIGNAL 00472 #endif 00473 ); 00474 00475 if (bytes_written < 0 && errno == EINTR) 00476 goto again; 00477 00478 #if 0 00479 if (bytes_written > 0) 00480 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00481 #endif 00482 00483 return bytes_written; 00484 #endif 00485 } 00486 00500 int 00501 _dbus_write_socket_two (int fd, 00502 const DBusString *buffer1, 00503 int start1, 00504 int len1, 00505 const DBusString *buffer2, 00506 int start2, 00507 int len2) 00508 { 00509 #if HAVE_DECL_MSG_NOSIGNAL 00510 struct iovec vectors[2]; 00511 const char *data1; 00512 const char *data2; 00513 int bytes_written; 00514 struct msghdr m; 00515 00516 _dbus_assert (buffer1 != NULL); 00517 _dbus_assert (start1 >= 0); 00518 _dbus_assert (start2 >= 0); 00519 _dbus_assert (len1 >= 0); 00520 _dbus_assert (len2 >= 0); 00521 00522 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00523 00524 if (buffer2 != NULL) 00525 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00526 else 00527 { 00528 data2 = NULL; 00529 start2 = 0; 00530 len2 = 0; 00531 } 00532 00533 vectors[0].iov_base = (char*) data1; 00534 vectors[0].iov_len = len1; 00535 vectors[1].iov_base = (char*) data2; 00536 vectors[1].iov_len = len2; 00537 00538 _DBUS_ZERO(m); 00539 m.msg_iov = vectors; 00540 m.msg_iovlen = data2 ? 2 : 1; 00541 00542 again: 00543 00544 bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL); 00545 00546 if (bytes_written < 0 && errno == EINTR) 00547 goto again; 00548 00549 return bytes_written; 00550 00551 #else 00552 return _dbus_write_two (fd, buffer1, start1, len1, 00553 buffer2, start2, len2); 00554 #endif 00555 } 00556 00557 dbus_bool_t 00558 _dbus_socket_is_invalid (int fd) 00559 { 00560 return fd < 0 ? TRUE : FALSE; 00561 } 00562 00579 int 00580 _dbus_read (int fd, 00581 DBusString *buffer, 00582 int count) 00583 { 00584 int bytes_read; 00585 int start; 00586 char *data; 00587 00588 _dbus_assert (count >= 0); 00589 00590 start = _dbus_string_get_length (buffer); 00591 00592 if (!_dbus_string_lengthen (buffer, count)) 00593 { 00594 errno = ENOMEM; 00595 return -1; 00596 } 00597 00598 data = _dbus_string_get_data_len (buffer, start, count); 00599 00600 again: 00601 00602 bytes_read = read (fd, data, count); 00603 00604 if (bytes_read < 0) 00605 { 00606 if (errno == EINTR) 00607 goto again; 00608 else 00609 { 00610 /* put length back (note that this doesn't actually realloc anything) */ 00611 _dbus_string_set_length (buffer, start); 00612 return -1; 00613 } 00614 } 00615 else 00616 { 00617 /* put length back (doesn't actually realloc) */ 00618 _dbus_string_set_length (buffer, start + bytes_read); 00619 00620 #if 0 00621 if (bytes_read > 0) 00622 _dbus_verbose_bytes_of_string (buffer, start, bytes_read); 00623 #endif 00624 00625 return bytes_read; 00626 } 00627 } 00628 00639 int 00640 _dbus_write (int fd, 00641 const DBusString *buffer, 00642 int start, 00643 int len) 00644 { 00645 const char *data; 00646 int bytes_written; 00647 00648 data = _dbus_string_get_const_data_len (buffer, start, len); 00649 00650 again: 00651 00652 bytes_written = write (fd, data, len); 00653 00654 if (bytes_written < 0 && errno == EINTR) 00655 goto again; 00656 00657 #if 0 00658 if (bytes_written > 0) 00659 _dbus_verbose_bytes_of_string (buffer, start, bytes_written); 00660 #endif 00661 00662 return bytes_written; 00663 } 00664 00685 int 00686 _dbus_write_two (int fd, 00687 const DBusString *buffer1, 00688 int start1, 00689 int len1, 00690 const DBusString *buffer2, 00691 int start2, 00692 int len2) 00693 { 00694 _dbus_assert (buffer1 != NULL); 00695 _dbus_assert (start1 >= 0); 00696 _dbus_assert (start2 >= 0); 00697 _dbus_assert (len1 >= 0); 00698 _dbus_assert (len2 >= 0); 00699 00700 #ifdef HAVE_WRITEV 00701 { 00702 struct iovec vectors[2]; 00703 const char *data1; 00704 const char *data2; 00705 int bytes_written; 00706 00707 data1 = _dbus_string_get_const_data_len (buffer1, start1, len1); 00708 00709 if (buffer2 != NULL) 00710 data2 = _dbus_string_get_const_data_len (buffer2, start2, len2); 00711 else 00712 { 00713 data2 = NULL; 00714 start2 = 0; 00715 len2 = 0; 00716 } 00717 00718 vectors[0].iov_base = (char*) data1; 00719 vectors[0].iov_len = len1; 00720 vectors[1].iov_base = (char*) data2; 00721 vectors[1].iov_len = len2; 00722 00723 again: 00724 00725 bytes_written = writev (fd, 00726 vectors, 00727 data2 ? 2 : 1); 00728 00729 if (bytes_written < 0 && errno == EINTR) 00730 goto again; 00731 00732 return bytes_written; 00733 } 00734 #else /* HAVE_WRITEV */ 00735 { 00736 int ret1; 00737 00738 ret1 = _dbus_write (fd, buffer1, start1, len1); 00739 if (ret1 == len1 && buffer2 != NULL) 00740 { 00741 ret2 = _dbus_write (fd, buffer2, start2, len2); 00742 if (ret2 < 0) 00743 ret2 = 0; /* we can't report an error as the first write was OK */ 00744 00745 return ret1 + ret2; 00746 } 00747 else 00748 return ret1; 00749 } 00750 #endif /* !HAVE_WRITEV */ 00751 } 00752 00753 #define _DBUS_MAX_SUN_PATH_LENGTH 99 00754 00784 int 00785 _dbus_connect_unix_socket (const char *path, 00786 dbus_bool_t abstract, 00787 DBusError *error) 00788 { 00789 int fd; 00790 size_t path_len; 00791 struct sockaddr_un addr; 00792 00793 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00794 00795 _dbus_verbose ("connecting to unix socket %s abstract=%d\n", 00796 path, abstract); 00797 00798 00799 if (!_dbus_open_unix_socket (&fd, error)) 00800 { 00801 _DBUS_ASSERT_ERROR_IS_SET(error); 00802 return -1; 00803 } 00804 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 00805 00806 _DBUS_ZERO (addr); 00807 addr.sun_family = AF_UNIX; 00808 path_len = strlen (path); 00809 00810 if (abstract) 00811 { 00812 #ifdef HAVE_ABSTRACT_SOCKETS 00813 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 00814 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 00815 00816 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00817 { 00818 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00819 "Abstract socket name too long\n"); 00820 _dbus_close (fd, NULL); 00821 return -1; 00822 } 00823 00824 strncpy (&addr.sun_path[1], path, path_len); 00825 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 00826 #else /* HAVE_ABSTRACT_SOCKETS */ 00827 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 00828 "Operating system does not support abstract socket namespace\n"); 00829 _dbus_close (fd, NULL); 00830 return -1; 00831 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 00832 } 00833 else 00834 { 00835 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 00836 { 00837 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 00838 "Socket name too long\n"); 00839 _dbus_close (fd, NULL); 00840 return -1; 00841 } 00842 00843 strncpy (addr.sun_path, path, path_len); 00844 } 00845 00846 if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 00847 { 00848 dbus_set_error (error, 00849 _dbus_error_from_errno (errno), 00850 "Failed to connect to socket %s: %s", 00851 path, _dbus_strerror (errno)); 00852 00853 _dbus_close (fd, NULL); 00854 return -1; 00855 } 00856 00857 if (!_dbus_set_fd_nonblocking (fd, error)) 00858 { 00859 _DBUS_ASSERT_ERROR_IS_SET (error); 00860 00861 _dbus_close (fd, NULL); 00862 return -1; 00863 } 00864 00865 return fd; 00866 } 00867 00880 int 00881 _dbus_connect_exec (const char *path, 00882 char *const argv[], 00883 DBusError *error) 00884 { 00885 int fds[2]; 00886 pid_t pid; 00887 00888 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00889 00890 _dbus_verbose ("connecting to process %s\n", path); 00891 00892 if (socketpair (AF_UNIX, SOCK_STREAM 00893 #ifdef SOCK_CLOEXEC 00894 |SOCK_CLOEXEC 00895 #endif 00896 , 0, fds) < 0) 00897 { 00898 dbus_set_error (error, 00899 _dbus_error_from_errno (errno), 00900 "Failed to create socket pair: %s", 00901 _dbus_strerror (errno)); 00902 return -1; 00903 } 00904 00905 _dbus_fd_set_close_on_exec (fds[0]); 00906 _dbus_fd_set_close_on_exec (fds[1]); 00907 00908 pid = fork (); 00909 if (pid < 0) 00910 { 00911 dbus_set_error (error, 00912 _dbus_error_from_errno (errno), 00913 "Failed to fork() to call %s: %s", 00914 path, _dbus_strerror (errno)); 00915 close (fds[0]); 00916 close (fds[1]); 00917 return -1; 00918 } 00919 00920 if (pid == 0) 00921 { 00922 /* child */ 00923 close (fds[0]); 00924 00925 dup2 (fds[1], STDIN_FILENO); 00926 dup2 (fds[1], STDOUT_FILENO); 00927 00928 if (fds[1] != STDIN_FILENO && 00929 fds[1] != STDOUT_FILENO) 00930 close (fds[1]); 00931 00932 /* Inherit STDERR and the controlling terminal from the 00933 parent */ 00934 00935 _dbus_close_all (); 00936 00937 execvp (path, argv); 00938 00939 fprintf (stderr, "Failed to execute process %s: %s\n", path, _dbus_strerror (errno)); 00940 00941 _exit(1); 00942 } 00943 00944 /* parent */ 00945 close (fds[1]); 00946 00947 if (!_dbus_set_fd_nonblocking (fds[0], error)) 00948 { 00949 _DBUS_ASSERT_ERROR_IS_SET (error); 00950 00951 close (fds[0]); 00952 return -1; 00953 } 00954 00955 return fds[0]; 00956 } 00957 00967 static dbus_bool_t 00968 _dbus_set_local_creds (int fd, dbus_bool_t on) 00969 { 00970 dbus_bool_t retval = TRUE; 00971 00972 #if defined(HAVE_CMSGCRED) 00973 /* NOOP just to make sure only one codepath is used 00974 * and to prefer CMSGCRED 00975 */ 00976 #elif defined(LOCAL_CREDS) 00977 int val = on ? 1 : 0; 00978 if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) 00979 { 00980 _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); 00981 retval = FALSE; 00982 } 00983 else 00984 _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", 00985 on ? "enabled" : "disabled", fd); 00986 #endif 00987 00988 return retval; 00989 } 00990 01008 int 01009 _dbus_listen_unix_socket (const char *path, 01010 dbus_bool_t abstract, 01011 DBusError *error) 01012 { 01013 int listen_fd; 01014 struct sockaddr_un addr; 01015 size_t path_len; 01016 unsigned int reuseaddr; 01017 01018 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01019 01020 _dbus_verbose ("listening on unix socket %s abstract=%d\n", 01021 path, abstract); 01022 01023 if (!_dbus_open_unix_socket (&listen_fd, error)) 01024 { 01025 _DBUS_ASSERT_ERROR_IS_SET(error); 01026 return -1; 01027 } 01028 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01029 01030 _DBUS_ZERO (addr); 01031 addr.sun_family = AF_UNIX; 01032 path_len = strlen (path); 01033 01034 if (abstract) 01035 { 01036 #ifdef HAVE_ABSTRACT_SOCKETS 01037 /* remember that abstract names aren't nul-terminated so we rely 01038 * on sun_path being filled in with zeroes above. 01039 */ 01040 addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ 01041 path_len++; /* Account for the extra nul byte added to the start of sun_path */ 01042 01043 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01044 { 01045 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01046 "Abstract socket name too long\n"); 01047 _dbus_close (listen_fd, NULL); 01048 return -1; 01049 } 01050 01051 strncpy (&addr.sun_path[1], path, path_len); 01052 /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ 01053 #else /* HAVE_ABSTRACT_SOCKETS */ 01054 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, 01055 "Operating system does not support abstract socket namespace\n"); 01056 _dbus_close (listen_fd, NULL); 01057 return -1; 01058 #endif /* ! HAVE_ABSTRACT_SOCKETS */ 01059 } 01060 else 01061 { 01062 /* Discussed security implications of this with Nalin, 01063 * and we couldn't think of where it would kick our ass, but 01064 * it still seems a bit sucky. It also has non-security suckage; 01065 * really we'd prefer to exit if the socket is already in use. 01066 * But there doesn't seem to be a good way to do this. 01067 * 01068 * Just to be extra careful, I threw in the stat() - clearly 01069 * the stat() can't *fix* any security issue, but it at least 01070 * avoids inadvertent/accidental data loss. 01071 */ 01072 { 01073 struct stat sb; 01074 01075 if (stat (path, &sb) == 0 && 01076 S_ISSOCK (sb.st_mode)) 01077 unlink (path); 01078 } 01079 01080 if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) 01081 { 01082 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01083 "Abstract socket name too long\n"); 01084 _dbus_close (listen_fd, NULL); 01085 return -1; 01086 } 01087 01088 strncpy (addr.sun_path, path, path_len); 01089 } 01090 01091 reuseaddr = 1; 01092 if (setsockopt (listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01093 { 01094 _dbus_warn ("Failed to set socket option\"%s\": %s", 01095 path, _dbus_strerror (errno)); 01096 } 01097 01098 if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) 01099 { 01100 dbus_set_error (error, _dbus_error_from_errno (errno), 01101 "Failed to bind socket \"%s\": %s", 01102 path, _dbus_strerror (errno)); 01103 _dbus_close (listen_fd, NULL); 01104 return -1; 01105 } 01106 01107 if (listen (listen_fd, 30 /* backlog */) < 0) 01108 { 01109 dbus_set_error (error, _dbus_error_from_errno (errno), 01110 "Failed to listen on socket \"%s\": %s", 01111 path, _dbus_strerror (errno)); 01112 _dbus_close (listen_fd, NULL); 01113 return -1; 01114 } 01115 01116 if (!_dbus_set_local_creds (listen_fd, TRUE)) 01117 { 01118 dbus_set_error (error, _dbus_error_from_errno (errno), 01119 "Failed to enable LOCAL_CREDS on socket \"%s\": %s", 01120 path, _dbus_strerror (errno)); 01121 close (listen_fd); 01122 return -1; 01123 } 01124 01125 if (!_dbus_set_fd_nonblocking (listen_fd, error)) 01126 { 01127 _DBUS_ASSERT_ERROR_IS_SET (error); 01128 _dbus_close (listen_fd, NULL); 01129 return -1; 01130 } 01131 01132 /* Try opening up the permissions, but if we can't, just go ahead 01133 * and continue, maybe it will be good enough. 01134 */ 01135 if (!abstract && chmod (path, 0777) < 0) 01136 _dbus_warn ("Could not set mode 0777 on socket %s\n", 01137 path); 01138 01139 return listen_fd; 01140 } 01141 01152 int 01153 _dbus_listen_systemd_sockets (int **fds, 01154 DBusError *error) 01155 { 01156 int r, n; 01157 unsigned fd; 01158 int *new_fds; 01159 01160 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01161 01162 n = sd_listen_fds (TRUE); 01163 if (n < 0) 01164 { 01165 dbus_set_error (error, _dbus_error_from_errno (-n), 01166 "Failed to acquire systemd socket: %s", 01167 _dbus_strerror (-n)); 01168 return -1; 01169 } 01170 01171 if (n <= 0) 01172 { 01173 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01174 "No socket received."); 01175 return -1; 01176 } 01177 01178 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01179 { 01180 r = sd_is_socket (fd, AF_UNSPEC, SOCK_STREAM, 1); 01181 if (r < 0) 01182 { 01183 dbus_set_error (error, _dbus_error_from_errno (-r), 01184 "Failed to verify systemd socket type: %s", 01185 _dbus_strerror (-r)); 01186 return -1; 01187 } 01188 01189 if (!r) 01190 { 01191 dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, 01192 "Passed socket has wrong type."); 01193 return -1; 01194 } 01195 } 01196 01197 /* OK, the file descriptors are all good, so let's take posession of 01198 them then. */ 01199 01200 new_fds = dbus_new (int, n); 01201 if (!new_fds) 01202 { 01203 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 01204 "Failed to allocate file handle array."); 01205 goto fail; 01206 } 01207 01208 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01209 { 01210 if (!_dbus_set_local_creds (fd, TRUE)) 01211 { 01212 dbus_set_error (error, _dbus_error_from_errno (errno), 01213 "Failed to enable LOCAL_CREDS on systemd socket: %s", 01214 _dbus_strerror (errno)); 01215 goto fail; 01216 } 01217 01218 if (!_dbus_set_fd_nonblocking (fd, error)) 01219 { 01220 _DBUS_ASSERT_ERROR_IS_SET (error); 01221 goto fail; 01222 } 01223 01224 new_fds[fd - SD_LISTEN_FDS_START] = fd; 01225 } 01226 01227 *fds = new_fds; 01228 return n; 01229 01230 fail: 01231 01232 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) 01233 { 01234 _dbus_close (fd, NULL); 01235 } 01236 01237 dbus_free (new_fds); 01238 return -1; 01239 } 01240 01254 int 01255 _dbus_connect_tcp_socket (const char *host, 01256 const char *port, 01257 const char *family, 01258 DBusError *error) 01259 { 01260 return _dbus_connect_tcp_socket_with_nonce (host, port, family, (const char*)NULL, error); 01261 } 01262 01263 int 01264 _dbus_connect_tcp_socket_with_nonce (const char *host, 01265 const char *port, 01266 const char *family, 01267 const char *noncefile, 01268 DBusError *error) 01269 { 01270 int saved_errno = 0; 01271 int fd = -1, res; 01272 struct addrinfo hints; 01273 struct addrinfo *ai, *tmp; 01274 01275 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01276 01277 _DBUS_ZERO (hints); 01278 01279 if (!family) 01280 hints.ai_family = AF_UNSPEC; 01281 else if (!strcmp(family, "ipv4")) 01282 hints.ai_family = AF_INET; 01283 else if (!strcmp(family, "ipv6")) 01284 hints.ai_family = AF_INET6; 01285 else 01286 { 01287 dbus_set_error (error, 01288 DBUS_ERROR_BAD_ADDRESS, 01289 "Unknown address family %s", family); 01290 return -1; 01291 } 01292 hints.ai_protocol = IPPROTO_TCP; 01293 hints.ai_socktype = SOCK_STREAM; 01294 hints.ai_flags = AI_ADDRCONFIG; 01295 01296 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0) 01297 { 01298 dbus_set_error (error, 01299 _dbus_error_from_errno (errno), 01300 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01301 host, port, gai_strerror(res), res); 01302 return -1; 01303 } 01304 01305 tmp = ai; 01306 while (tmp) 01307 { 01308 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01309 { 01310 freeaddrinfo(ai); 01311 _DBUS_ASSERT_ERROR_IS_SET(error); 01312 return -1; 01313 } 01314 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01315 01316 if (connect (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01317 { 01318 saved_errno = errno; 01319 _dbus_close(fd, NULL); 01320 fd = -1; 01321 tmp = tmp->ai_next; 01322 continue; 01323 } 01324 01325 break; 01326 } 01327 freeaddrinfo(ai); 01328 01329 if (fd == -1) 01330 { 01331 dbus_set_error (error, 01332 _dbus_error_from_errno (saved_errno), 01333 "Failed to connect to socket \"%s:%s\" %s", 01334 host, port, _dbus_strerror(saved_errno)); 01335 return -1; 01336 } 01337 01338 if (noncefile != NULL) 01339 { 01340 DBusString noncefileStr; 01341 dbus_bool_t ret; 01342 _dbus_string_init_const (&noncefileStr, noncefile); 01343 ret = _dbus_send_nonce (fd, &noncefileStr, error); 01344 _dbus_string_free (&noncefileStr); 01345 01346 if (!ret) 01347 { 01348 _dbus_close (fd, NULL); 01349 return -1; 01350 } 01351 } 01352 01353 if (!_dbus_set_fd_nonblocking (fd, error)) 01354 { 01355 _dbus_close (fd, NULL); 01356 return -1; 01357 } 01358 01359 return fd; 01360 } 01361 01378 int 01379 _dbus_listen_tcp_socket (const char *host, 01380 const char *port, 01381 const char *family, 01382 DBusString *retport, 01383 int **fds_p, 01384 DBusError *error) 01385 { 01386 int saved_errno; 01387 int nlisten_fd = 0, *listen_fd = NULL, res, i; 01388 struct addrinfo hints; 01389 struct addrinfo *ai, *tmp; 01390 unsigned int reuseaddr; 01391 01392 *fds_p = NULL; 01393 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01394 01395 _DBUS_ZERO (hints); 01396 01397 if (!family) 01398 hints.ai_family = AF_UNSPEC; 01399 else if (!strcmp(family, "ipv4")) 01400 hints.ai_family = AF_INET; 01401 else if (!strcmp(family, "ipv6")) 01402 hints.ai_family = AF_INET6; 01403 else 01404 { 01405 dbus_set_error (error, 01406 DBUS_ERROR_BAD_ADDRESS, 01407 "Unknown address family %s", family); 01408 return -1; 01409 } 01410 01411 hints.ai_protocol = IPPROTO_TCP; 01412 hints.ai_socktype = SOCK_STREAM; 01413 hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; 01414 01415 redo_lookup_with_port: 01416 ai = NULL; 01417 if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai) 01418 { 01419 dbus_set_error (error, 01420 _dbus_error_from_errno (errno), 01421 "Failed to lookup host/port: \"%s:%s\": %s (%d)", 01422 host ? host : "*", port, gai_strerror(res), res); 01423 goto failed; 01424 } 01425 01426 tmp = ai; 01427 while (tmp) 01428 { 01429 int fd = -1, *newlisten_fd; 01430 if (!_dbus_open_socket (&fd, tmp->ai_family, SOCK_STREAM, 0, error)) 01431 { 01432 _DBUS_ASSERT_ERROR_IS_SET(error); 01433 goto failed; 01434 } 01435 _DBUS_ASSERT_ERROR_IS_CLEAR(error); 01436 01437 reuseaddr = 1; 01438 if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr))==-1) 01439 { 01440 _dbus_warn ("Failed to set socket option \"%s:%s\": %s", 01441 host ? host : "*", port, _dbus_strerror (errno)); 01442 } 01443 01444 if (bind (fd, (struct sockaddr*) tmp->ai_addr, tmp->ai_addrlen) < 0) 01445 { 01446 saved_errno = errno; 01447 _dbus_close(fd, NULL); 01448 if (saved_errno == EADDRINUSE) 01449 { 01450 /* Depending on kernel policy, it may or may not 01451 be neccessary to bind to both IPv4 & 6 addresses 01452 so ignore EADDRINUSE here */ 01453 tmp = tmp->ai_next; 01454 continue; 01455 } 01456 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01457 "Failed to bind socket \"%s:%s\": %s", 01458 host ? host : "*", port, _dbus_strerror (saved_errno)); 01459 goto failed; 01460 } 01461 01462 if (listen (fd, 30 /* backlog */) < 0) 01463 { 01464 saved_errno = errno; 01465 _dbus_close (fd, NULL); 01466 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01467 "Failed to listen on socket \"%s:%s\": %s", 01468 host ? host : "*", port, _dbus_strerror (saved_errno)); 01469 goto failed; 01470 } 01471 01472 newlisten_fd = dbus_realloc(listen_fd, sizeof(int)*(nlisten_fd+1)); 01473 if (!newlisten_fd) 01474 { 01475 saved_errno = errno; 01476 _dbus_close (fd, NULL); 01477 dbus_set_error (error, _dbus_error_from_errno (saved_errno), 01478 "Failed to allocate file handle array: %s", 01479 _dbus_strerror (saved_errno)); 01480 goto failed; 01481 } 01482 listen_fd = newlisten_fd; 01483 listen_fd[nlisten_fd] = fd; 01484 nlisten_fd++; 01485 01486 if (!_dbus_string_get_length(retport)) 01487 { 01488 /* If the user didn't specify a port, or used 0, then 01489 the kernel chooses a port. After the first address 01490 is bound to, we need to force all remaining addresses 01491 to use the same port */ 01492 if (!port || !strcmp(port, "0")) 01493 { 01494 int result; 01495 struct sockaddr_storage addr; 01496 socklen_t addrlen; 01497 char portbuf[50]; 01498 01499 addrlen = sizeof(addr); 01500 result = getsockname(fd, (struct sockaddr*) &addr, &addrlen); 01501 01502 if (result == -1 || 01503 (res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0, 01504 portbuf, sizeof(portbuf), 01505 NI_NUMERICHOST)) != 0) 01506 { 01507 dbus_set_error (error, _dbus_error_from_errno (errno), 01508 "Failed to resolve port \"%s:%s\": %s (%s)", 01509 host ? host : "*", port, gai_strerror(res), res); 01510 goto failed; 01511 } 01512 if (!_dbus_string_append(retport, portbuf)) 01513 { 01514 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01515 goto failed; 01516 } 01517 01518 /* Release current address list & redo lookup */ 01519 port = _dbus_string_get_const_data(retport); 01520 freeaddrinfo(ai); 01521 goto redo_lookup_with_port; 01522 } 01523 else 01524 { 01525 if (!_dbus_string_append(retport, port)) 01526 { 01527 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01528 goto failed; 01529 } 01530 } 01531 } 01532 01533 tmp = tmp->ai_next; 01534 } 01535 freeaddrinfo(ai); 01536 ai = NULL; 01537 01538 if (!nlisten_fd) 01539 { 01540 errno = EADDRINUSE; 01541 dbus_set_error (error, _dbus_error_from_errno (errno), 01542 "Failed to bind socket \"%s:%s\": %s", 01543 host ? host : "*", port, _dbus_strerror (errno)); 01544 goto failed; 01545 } 01546 01547 for (i = 0 ; i < nlisten_fd ; i++) 01548 { 01549 if (!_dbus_set_fd_nonblocking (listen_fd[i], error)) 01550 { 01551 goto failed; 01552 } 01553 } 01554 01555 *fds_p = listen_fd; 01556 01557 return nlisten_fd; 01558 01559 failed: 01560 if (ai) 01561 freeaddrinfo(ai); 01562 for (i = 0 ; i < nlisten_fd ; i++) 01563 _dbus_close(listen_fd[i], NULL); 01564 dbus_free(listen_fd); 01565 return -1; 01566 } 01567 01568 static dbus_bool_t 01569 write_credentials_byte (int server_fd, 01570 DBusError *error) 01571 { 01572 int bytes_written; 01573 char buf[1] = { '\0' }; 01574 #if defined(HAVE_CMSGCRED) 01575 union { 01576 struct cmsghdr hdr; 01577 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01578 } cmsg; 01579 struct iovec iov; 01580 struct msghdr msg; 01581 iov.iov_base = buf; 01582 iov.iov_len = 1; 01583 01584 _DBUS_ZERO(msg); 01585 msg.msg_iov = &iov; 01586 msg.msg_iovlen = 1; 01587 01588 msg.msg_control = (caddr_t) &cmsg; 01589 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01590 _DBUS_ZERO(cmsg); 01591 cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred)); 01592 cmsg.hdr.cmsg_level = SOL_SOCKET; 01593 cmsg.hdr.cmsg_type = SCM_CREDS; 01594 #endif 01595 01596 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01597 01598 again: 01599 01600 #if defined(HAVE_CMSGCRED) 01601 bytes_written = sendmsg (server_fd, &msg, 0 01602 #if HAVE_DECL_MSG_NOSIGNAL 01603 |MSG_NOSIGNAL 01604 #endif 01605 ); 01606 #else 01607 bytes_written = send (server_fd, buf, 1, 0 01608 #if HAVE_DECL_MSG_NOSIGNAL 01609 |MSG_NOSIGNAL 01610 #endif 01611 ); 01612 #endif 01613 01614 if (bytes_written < 0 && errno == EINTR) 01615 goto again; 01616 01617 if (bytes_written < 0) 01618 { 01619 dbus_set_error (error, _dbus_error_from_errno (errno), 01620 "Failed to write credentials byte: %s", 01621 _dbus_strerror (errno)); 01622 return FALSE; 01623 } 01624 else if (bytes_written == 0) 01625 { 01626 dbus_set_error (error, DBUS_ERROR_IO_ERROR, 01627 "wrote zero bytes writing credentials byte"); 01628 return FALSE; 01629 } 01630 else 01631 { 01632 _dbus_assert (bytes_written == 1); 01633 _dbus_verbose ("wrote credentials byte\n"); 01634 return TRUE; 01635 } 01636 } 01637 01659 dbus_bool_t 01660 _dbus_read_credentials_socket (int client_fd, 01661 DBusCredentials *credentials, 01662 DBusError *error) 01663 { 01664 struct msghdr msg; 01665 struct iovec iov; 01666 char buf; 01667 dbus_uid_t uid_read; 01668 dbus_pid_t pid_read; 01669 int bytes_read; 01670 01671 #ifdef HAVE_CMSGCRED 01672 union { 01673 struct cmsghdr hdr; 01674 char cred[CMSG_SPACE (sizeof (struct cmsgcred))]; 01675 } cmsg; 01676 01677 #elif defined(LOCAL_CREDS) 01678 struct { 01679 struct cmsghdr hdr; 01680 struct sockcred cred; 01681 } cmsg; 01682 #endif 01683 01684 uid_read = DBUS_UID_UNSET; 01685 pid_read = DBUS_PID_UNSET; 01686 01687 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01688 01689 /* The POSIX spec certainly doesn't promise this, but 01690 * we need these assertions to fail as soon as we're wrong about 01691 * it so we can do the porting fixups 01692 */ 01693 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 01694 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 01695 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 01696 01697 _dbus_credentials_clear (credentials); 01698 01699 /* Systems supporting LOCAL_CREDS are configured to have this feature 01700 * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting 01701 * the connection. Therefore, the received message must carry the 01702 * credentials information without doing anything special. 01703 */ 01704 01705 iov.iov_base = &buf; 01706 iov.iov_len = 1; 01707 01708 _DBUS_ZERO(msg); 01709 msg.msg_iov = &iov; 01710 msg.msg_iovlen = 1; 01711 01712 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01713 _DBUS_ZERO(cmsg); 01714 msg.msg_control = (caddr_t) &cmsg; 01715 msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred)); 01716 #endif 01717 01718 again: 01719 bytes_read = recvmsg (client_fd, &msg, 0); 01720 01721 if (bytes_read < 0) 01722 { 01723 if (errno == EINTR) 01724 goto again; 01725 01726 /* EAGAIN or EWOULDBLOCK would be unexpected here since we would 01727 * normally only call read_credentials if the socket was ready 01728 * for reading 01729 */ 01730 01731 dbus_set_error (error, _dbus_error_from_errno (errno), 01732 "Failed to read credentials byte: %s", 01733 _dbus_strerror (errno)); 01734 return FALSE; 01735 } 01736 else if (bytes_read == 0) 01737 { 01738 /* this should not happen unless we are using recvmsg wrong, 01739 * so is essentially here for paranoia 01740 */ 01741 dbus_set_error (error, DBUS_ERROR_FAILED, 01742 "Failed to read credentials byte (zero-length read)"); 01743 return FALSE; 01744 } 01745 else if (buf != '\0') 01746 { 01747 dbus_set_error (error, DBUS_ERROR_FAILED, 01748 "Credentials byte was not nul"); 01749 return FALSE; 01750 } 01751 01752 #if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) 01753 if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) 01754 || cmsg.hdr.cmsg_type != SCM_CREDS) 01755 { 01756 dbus_set_error (error, DBUS_ERROR_FAILED, 01757 "Message from recvmsg() was not SCM_CREDS"); 01758 return FALSE; 01759 } 01760 #endif 01761 01762 _dbus_verbose ("read credentials byte\n"); 01763 01764 { 01765 #ifdef SO_PEERCRED 01766 #ifdef __OpenBSD__ 01767 struct sockpeercred cr; 01768 #else 01769 struct ucred cr; 01770 #endif 01771 int cr_len = sizeof (cr); 01772 01773 if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && 01774 cr_len == sizeof (cr)) 01775 { 01776 pid_read = cr.pid; 01777 uid_read = cr.uid; 01778 } 01779 else 01780 { 01781 _dbus_verbose ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", 01782 cr_len, (int) sizeof (cr), _dbus_strerror (errno)); 01783 } 01784 #elif defined(HAVE_CMSGCRED) 01785 struct cmsgcred *cred; 01786 01787 cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); 01788 pid_read = cred->cmcred_pid; 01789 uid_read = cred->cmcred_euid; 01790 #elif defined(LOCAL_CREDS) 01791 pid_read = DBUS_PID_UNSET; 01792 uid_read = cmsg.cred.sc_uid; 01793 /* Since we have already got the credentials from this socket, we can 01794 * disable its LOCAL_CREDS flag if it was ever set. */ 01795 _dbus_set_local_creds (client_fd, FALSE); 01796 #elif defined(HAVE_GETPEEREID) 01797 uid_t euid; 01798 gid_t egid; 01799 if (getpeereid (client_fd, &euid, &egid) == 0) 01800 { 01801 uid_read = euid; 01802 } 01803 else 01804 { 01805 _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); 01806 } 01807 #elif defined(HAVE_GETPEERUCRED) 01808 ucred_t * ucred = NULL; 01809 if (getpeerucred (client_fd, &ucred) == 0) 01810 { 01811 pid_read = ucred_getpid (ucred); 01812 uid_read = ucred_geteuid (ucred); 01813 #ifdef HAVE_ADT 01814 /* generate audit session data based on socket ucred */ 01815 adt_session_data_t *adth = NULL; 01816 adt_export_data_t *data = NULL; 01817 size_t size = 0; 01818 if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) 01819 { 01820 _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); 01821 } 01822 else 01823 { 01824 if (adt_set_from_ucred (adth, ucred, ADT_NEW)) 01825 { 01826 _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); 01827 } 01828 else 01829 { 01830 size = adt_export_session_data (adth, &data); 01831 if (size <= 0) 01832 { 01833 _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); 01834 } 01835 else 01836 { 01837 _dbus_credentials_add_adt_audit_data (credentials, data, size); 01838 free (data); 01839 } 01840 } 01841 (void) adt_end_session (adth); 01842 } 01843 #endif /* HAVE_ADT */ 01844 } 01845 else 01846 { 01847 _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); 01848 } 01849 if (ucred != NULL) 01850 ucred_free (ucred); 01851 #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ 01852 _dbus_verbose ("Socket credentials not supported on this OS\n"); 01853 #endif 01854 } 01855 01856 _dbus_verbose ("Credentials:" 01857 " pid "DBUS_PID_FORMAT 01858 " uid "DBUS_UID_FORMAT 01859 "\n", 01860 pid_read, 01861 uid_read); 01862 01863 if (pid_read != DBUS_PID_UNSET) 01864 { 01865 if (!_dbus_credentials_add_unix_pid (credentials, pid_read)) 01866 { 01867 _DBUS_SET_OOM (error); 01868 return FALSE; 01869 } 01870 } 01871 01872 if (uid_read != DBUS_UID_UNSET) 01873 { 01874 if (!_dbus_credentials_add_unix_uid (credentials, uid_read)) 01875 { 01876 _DBUS_SET_OOM (error); 01877 return FALSE; 01878 } 01879 } 01880 01881 return TRUE; 01882 } 01883 01901 dbus_bool_t 01902 _dbus_send_credentials_socket (int server_fd, 01903 DBusError *error) 01904 { 01905 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01906 01907 if (write_credentials_byte (server_fd, error)) 01908 return TRUE; 01909 else 01910 return FALSE; 01911 } 01912 01922 int 01923 _dbus_accept (int listen_fd) 01924 { 01925 int client_fd; 01926 struct sockaddr addr; 01927 socklen_t addrlen; 01928 #ifdef HAVE_ACCEPT4 01929 dbus_bool_t cloexec_done; 01930 #endif 01931 01932 addrlen = sizeof (addr); 01933 01934 retry: 01935 01936 #ifdef HAVE_ACCEPT4 01937 /* We assume that if accept4 is available SOCK_CLOEXEC is too */ 01938 client_fd = accept4 (listen_fd, &addr, &addrlen, SOCK_CLOEXEC); 01939 cloexec_done = client_fd >= 0; 01940 01941 if (client_fd < 0 && errno == ENOSYS) 01942 #endif 01943 { 01944 client_fd = accept (listen_fd, &addr, &addrlen); 01945 } 01946 01947 if (client_fd < 0) 01948 { 01949 if (errno == EINTR) 01950 goto retry; 01951 } 01952 01953 _dbus_verbose ("client fd %d accepted\n", client_fd); 01954 01955 #ifdef HAVE_ACCEPT4 01956 if (!cloexec_done) 01957 #endif 01958 { 01959 _dbus_fd_set_close_on_exec(client_fd); 01960 } 01961 01962 return client_fd; 01963 } 01964 01973 dbus_bool_t 01974 _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) 01975 { 01976 const char *directory; 01977 struct stat sb; 01978 01979 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01980 01981 directory = _dbus_string_get_const_data (dir); 01982 01983 if (stat (directory, &sb) < 0) 01984 { 01985 dbus_set_error (error, _dbus_error_from_errno (errno), 01986 "%s", _dbus_strerror (errno)); 01987 01988 return FALSE; 01989 } 01990 01991 if ((S_IROTH & sb.st_mode) || (S_IWOTH & sb.st_mode) || 01992 (S_IRGRP & sb.st_mode) || (S_IWGRP & sb.st_mode)) 01993 { 01994 dbus_set_error (error, DBUS_ERROR_FAILED, 01995 "%s directory is not private to the user", directory); 01996 return FALSE; 01997 } 01998 01999 return TRUE; 02000 } 02001 02002 static dbus_bool_t 02003 fill_user_info_from_passwd (struct passwd *p, 02004 DBusUserInfo *info, 02005 DBusError *error) 02006 { 02007 _dbus_assert (p->pw_name != NULL); 02008 _dbus_assert (p->pw_dir != NULL); 02009 02010 info->uid = p->pw_uid; 02011 info->primary_gid = p->pw_gid; 02012 info->username = _dbus_strdup (p->pw_name); 02013 info->homedir = _dbus_strdup (p->pw_dir); 02014 02015 if (info->username == NULL || 02016 info->homedir == NULL) 02017 { 02018 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02019 return FALSE; 02020 } 02021 02022 return TRUE; 02023 } 02024 02025 static dbus_bool_t 02026 fill_user_info (DBusUserInfo *info, 02027 dbus_uid_t uid, 02028 const DBusString *username, 02029 DBusError *error) 02030 { 02031 const char *username_c; 02032 02033 /* exactly one of username/uid provided */ 02034 _dbus_assert (username != NULL || uid != DBUS_UID_UNSET); 02035 _dbus_assert (username == NULL || uid == DBUS_UID_UNSET); 02036 02037 info->uid = DBUS_UID_UNSET; 02038 info->primary_gid = DBUS_GID_UNSET; 02039 info->group_ids = NULL; 02040 info->n_group_ids = 0; 02041 info->username = NULL; 02042 info->homedir = NULL; 02043 02044 if (username != NULL) 02045 username_c = _dbus_string_get_const_data (username); 02046 else 02047 username_c = NULL; 02048 02049 /* For now assuming that the getpwnam() and getpwuid() flavors 02050 * are always symmetrical, if not we have to add more configure 02051 * checks 02052 */ 02053 02054 #if defined (HAVE_POSIX_GETPWNAM_R) || defined (HAVE_NONPOSIX_GETPWNAM_R) 02055 { 02056 struct passwd *p; 02057 int result; 02058 size_t buflen; 02059 char *buf; 02060 struct passwd p_str; 02061 02062 /* retrieve maximum needed size for buf */ 02063 buflen = sysconf (_SC_GETPW_R_SIZE_MAX); 02064 02065 /* sysconf actually returns a long, but everything else expects size_t, 02066 * so just recast here. 02067 * https://bugs.freedesktop.org/show_bug.cgi?id=17061 02068 */ 02069 if ((long) buflen <= 0) 02070 buflen = 1024; 02071 02072 result = -1; 02073 while (1) 02074 { 02075 buf = dbus_malloc (buflen); 02076 if (buf == NULL) 02077 { 02078 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02079 return FALSE; 02080 } 02081 02082 p = NULL; 02083 #ifdef HAVE_POSIX_GETPWNAM_R 02084 if (uid != DBUS_UID_UNSET) 02085 result = getpwuid_r (uid, &p_str, buf, buflen, 02086 &p); 02087 else 02088 result = getpwnam_r (username_c, &p_str, buf, buflen, 02089 &p); 02090 #else 02091 if (uid != DBUS_UID_UNSET) 02092 p = getpwuid_r (uid, &p_str, buf, buflen); 02093 else 02094 p = getpwnam_r (username_c, &p_str, buf, buflen); 02095 result = 0; 02096 #endif /* !HAVE_POSIX_GETPWNAM_R */ 02097 //Try a bigger buffer if ERANGE was returned 02098 if (result == ERANGE && buflen < 512 * 1024) 02099 { 02100 dbus_free (buf); 02101 buflen *= 2; 02102 } 02103 else 02104 { 02105 break; 02106 } 02107 } 02108 if (result == 0 && p == &p_str) 02109 { 02110 if (!fill_user_info_from_passwd (p, info, error)) 02111 { 02112 dbus_free (buf); 02113 return FALSE; 02114 } 02115 dbus_free (buf); 02116 } 02117 else 02118 { 02119 dbus_set_error (error, _dbus_error_from_errno (errno), 02120 "User \"%s\" unknown or no memory to allocate password entry\n", 02121 username_c ? username_c : "???"); 02122 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02123 dbus_free (buf); 02124 return FALSE; 02125 } 02126 } 02127 #else /* ! HAVE_GETPWNAM_R */ 02128 { 02129 /* I guess we're screwed on thread safety here */ 02130 struct passwd *p; 02131 02132 if (uid != DBUS_UID_UNSET) 02133 p = getpwuid (uid); 02134 else 02135 p = getpwnam (username_c); 02136 02137 if (p != NULL) 02138 { 02139 if (!fill_user_info_from_passwd (p, info, error)) 02140 { 02141 return FALSE; 02142 } 02143 } 02144 else 02145 { 02146 dbus_set_error (error, _dbus_error_from_errno (errno), 02147 "User \"%s\" unknown or no memory to allocate password entry\n", 02148 username_c ? username_c : "???"); 02149 _dbus_verbose ("User %s unknown\n", username_c ? username_c : "???"); 02150 return FALSE; 02151 } 02152 } 02153 #endif /* ! HAVE_GETPWNAM_R */ 02154 02155 /* Fill this in so we can use it to get groups */ 02156 username_c = info->username; 02157 02158 #ifdef HAVE_GETGROUPLIST 02159 { 02160 gid_t *buf; 02161 int buf_count; 02162 int i; 02163 int initial_buf_count; 02164 02165 initial_buf_count = 17; 02166 buf_count = initial_buf_count; 02167 buf = dbus_new (gid_t, buf_count); 02168 if (buf == NULL) 02169 { 02170 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02171 goto failed; 02172 } 02173 02174 if (getgrouplist (username_c, 02175 info->primary_gid, 02176 buf, &buf_count) < 0) 02177 { 02178 gid_t *new; 02179 /* Presumed cause of negative return code: buf has insufficient 02180 entries to hold the entire group list. The Linux behavior in this 02181 case is to pass back the actual number of groups in buf_count, but 02182 on Mac OS X 10.5, buf_count is unhelpfully left alone. 02183 So as a hack, try to help out a bit by guessing a larger 02184 number of groups, within reason.. might still fail, of course, 02185 but we can at least print a more informative message. I looked up 02186 the "right way" to do this by downloading Apple's own source code 02187 for the "id" command, and it turns out that they use an 02188 undocumented library function getgrouplist_2 (!) which is not 02189 declared in any header in /usr/include (!!). That did not seem 02190 like the way to go here. 02191 */ 02192 if (buf_count == initial_buf_count) 02193 { 02194 buf_count *= 16; /* Retry with an arbitrarily scaled-up array */ 02195 } 02196 new = dbus_realloc (buf, buf_count * sizeof (buf[0])); 02197 if (new == NULL) 02198 { 02199 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02200 dbus_free (buf); 02201 goto failed; 02202 } 02203 02204 buf = new; 02205 02206 errno = 0; 02207 if (getgrouplist (username_c, info->primary_gid, buf, &buf_count) < 0) 02208 { 02209 if (errno == 0) 02210 { 02211 _dbus_warn ("It appears that username \"%s\" is in more than %d groups.\nProceeding with just the first %d groups.", 02212 username_c, buf_count, buf_count); 02213 } 02214 else 02215 { 02216 dbus_set_error (error, 02217 _dbus_error_from_errno (errno), 02218 "Failed to get groups for username \"%s\" primary GID " 02219 DBUS_GID_FORMAT ": %s\n", 02220 username_c, info->primary_gid, 02221 _dbus_strerror (errno)); 02222 dbus_free (buf); 02223 goto failed; 02224 } 02225 } 02226 } 02227 02228 info->group_ids = dbus_new (dbus_gid_t, buf_count); 02229 if (info->group_ids == NULL) 02230 { 02231 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02232 dbus_free (buf); 02233 goto failed; 02234 } 02235 02236 for (i = 0; i < buf_count; ++i) 02237 info->group_ids[i] = buf[i]; 02238 02239 info->n_group_ids = buf_count; 02240 02241 dbus_free (buf); 02242 } 02243 #else /* HAVE_GETGROUPLIST */ 02244 { 02245 /* We just get the one group ID */ 02246 info->group_ids = dbus_new (dbus_gid_t, 1); 02247 if (info->group_ids == NULL) 02248 { 02249 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 02250 goto failed; 02251 } 02252 02253 info->n_group_ids = 1; 02254 02255 (info->group_ids)[0] = info->primary_gid; 02256 } 02257 #endif /* HAVE_GETGROUPLIST */ 02258 02259 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02260 02261 return TRUE; 02262 02263 failed: 02264 _DBUS_ASSERT_ERROR_IS_SET (error); 02265 return FALSE; 02266 } 02267 02276 dbus_bool_t 02277 _dbus_user_info_fill (DBusUserInfo *info, 02278 const DBusString *username, 02279 DBusError *error) 02280 { 02281 return fill_user_info (info, DBUS_UID_UNSET, 02282 username, error); 02283 } 02284 02293 dbus_bool_t 02294 _dbus_user_info_fill_uid (DBusUserInfo *info, 02295 dbus_uid_t uid, 02296 DBusError *error) 02297 { 02298 return fill_user_info (info, uid, 02299 NULL, error); 02300 } 02301 02309 dbus_bool_t 02310 _dbus_credentials_add_from_current_process (DBusCredentials *credentials) 02311 { 02312 /* The POSIX spec certainly doesn't promise this, but 02313 * we need these assertions to fail as soon as we're wrong about 02314 * it so we can do the porting fixups 02315 */ 02316 _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t)); 02317 _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t)); 02318 _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t)); 02319 02320 if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid())) 02321 return FALSE; 02322 if (!_dbus_credentials_add_unix_uid(credentials, _dbus_geteuid())) 02323 return FALSE; 02324 02325 return TRUE; 02326 } 02327 02339 dbus_bool_t 02340 _dbus_append_user_from_current_process (DBusString *str) 02341 { 02342 return _dbus_string_append_uint (str, 02343 _dbus_geteuid ()); 02344 } 02345 02350 dbus_pid_t 02351 _dbus_getpid (void) 02352 { 02353 return getpid (); 02354 } 02355 02359 dbus_uid_t 02360 _dbus_getuid (void) 02361 { 02362 return getuid (); 02363 } 02364 02368 dbus_uid_t 02369 _dbus_geteuid (void) 02370 { 02371 return geteuid (); 02372 } 02373 02380 unsigned long 02381 _dbus_pid_for_log (void) 02382 { 02383 return getpid (); 02384 } 02385 02393 dbus_bool_t 02394 _dbus_parse_uid (const DBusString *uid_str, 02395 dbus_uid_t *uid) 02396 { 02397 int end; 02398 long val; 02399 02400 if (_dbus_string_get_length (uid_str) == 0) 02401 { 02402 _dbus_verbose ("UID string was zero length\n"); 02403 return FALSE; 02404 } 02405 02406 val = -1; 02407 end = 0; 02408 if (!_dbus_string_parse_int (uid_str, 0, &val, 02409 &end)) 02410 { 02411 _dbus_verbose ("could not parse string as a UID\n"); 02412 return FALSE; 02413 } 02414 02415 if (end != _dbus_string_get_length (uid_str)) 02416 { 02417 _dbus_verbose ("string contained trailing stuff after UID\n"); 02418 return FALSE; 02419 } 02420 02421 *uid = val; 02422 02423 return TRUE; 02424 } 02425 02426 #if !DBUS_USE_SYNC 02427 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 02428 #endif 02429 02436 dbus_int32_t 02437 _dbus_atomic_inc (DBusAtomic *atomic) 02438 { 02439 #if DBUS_USE_SYNC 02440 return __sync_add_and_fetch(&atomic->value, 1)-1; 02441 #else 02442 dbus_int32_t res; 02443 _DBUS_LOCK (atomic); 02444 res = atomic->value; 02445 atomic->value += 1; 02446 _DBUS_UNLOCK (atomic); 02447 return res; 02448 #endif 02449 } 02450 02457 dbus_int32_t 02458 _dbus_atomic_dec (DBusAtomic *atomic) 02459 { 02460 #if DBUS_USE_SYNC 02461 return __sync_sub_and_fetch(&atomic->value, 1)+1; 02462 #else 02463 dbus_int32_t res; 02464 02465 _DBUS_LOCK (atomic); 02466 res = atomic->value; 02467 atomic->value -= 1; 02468 _DBUS_UNLOCK (atomic); 02469 return res; 02470 #endif 02471 } 02472 02480 dbus_int32_t 02481 _dbus_atomic_get (DBusAtomic *atomic) 02482 { 02483 #if DBUS_USE_SYNC 02484 __sync_synchronize (); 02485 return atomic->value; 02486 #else 02487 dbus_int32_t res; 02488 02489 _DBUS_LOCK (atomic); 02490 res = atomic->value; 02491 _DBUS_UNLOCK (atomic); 02492 return res; 02493 #endif 02494 } 02495 02504 int 02505 _dbus_poll (DBusPollFD *fds, 02506 int n_fds, 02507 int timeout_milliseconds) 02508 { 02509 #if defined(HAVE_POLL) && !defined(BROKEN_POLL) 02510 /* This big thing is a constant expression and should get optimized 02511 * out of existence. So it's more robust than a configure check at 02512 * no cost. 02513 */ 02514 if (_DBUS_POLLIN == POLLIN && 02515 _DBUS_POLLPRI == POLLPRI && 02516 _DBUS_POLLOUT == POLLOUT && 02517 _DBUS_POLLERR == POLLERR && 02518 _DBUS_POLLHUP == POLLHUP && 02519 _DBUS_POLLNVAL == POLLNVAL && 02520 sizeof (DBusPollFD) == sizeof (struct pollfd) && 02521 _DBUS_STRUCT_OFFSET (DBusPollFD, fd) == 02522 _DBUS_STRUCT_OFFSET (struct pollfd, fd) && 02523 _DBUS_STRUCT_OFFSET (DBusPollFD, events) == 02524 _DBUS_STRUCT_OFFSET (struct pollfd, events) && 02525 _DBUS_STRUCT_OFFSET (DBusPollFD, revents) == 02526 _DBUS_STRUCT_OFFSET (struct pollfd, revents)) 02527 { 02528 return poll ((struct pollfd*) fds, 02529 n_fds, 02530 timeout_milliseconds); 02531 } 02532 else 02533 { 02534 /* We have to convert the DBusPollFD to an array of 02535 * struct pollfd, poll, and convert back. 02536 */ 02537 _dbus_warn ("didn't implement poll() properly for this system yet\n"); 02538 return -1; 02539 } 02540 #else /* ! HAVE_POLL */ 02541 02542 fd_set read_set, write_set, err_set; 02543 int max_fd = 0; 02544 int i; 02545 struct timeval tv; 02546 int ready; 02547 02548 FD_ZERO (&read_set); 02549 FD_ZERO (&write_set); 02550 FD_ZERO (&err_set); 02551 02552 for (i = 0; i < n_fds; i++) 02553 { 02554 DBusPollFD *fdp = &fds[i]; 02555 02556 if (fdp->events & _DBUS_POLLIN) 02557 FD_SET (fdp->fd, &read_set); 02558 02559 if (fdp->events & _DBUS_POLLOUT) 02560 FD_SET (fdp->fd, &write_set); 02561 02562 FD_SET (fdp->fd, &err_set); 02563 02564 max_fd = MAX (max_fd, fdp->fd); 02565 } 02566 02567 tv.tv_sec = timeout_milliseconds / 1000; 02568 tv.tv_usec = (timeout_milliseconds % 1000) * 1000; 02569 02570 ready = select (max_fd + 1, &read_set, &write_set, &err_set, 02571 timeout_milliseconds < 0 ? NULL : &tv); 02572 02573 if (ready > 0) 02574 { 02575 for (i = 0; i < n_fds; i++) 02576 { 02577 DBusPollFD *fdp = &fds[i]; 02578 02579 fdp->revents = 0; 02580 02581 if (FD_ISSET (fdp->fd, &read_set)) 02582 fdp->revents |= _DBUS_POLLIN; 02583 02584 if (FD_ISSET (fdp->fd, &write_set)) 02585 fdp->revents |= _DBUS_POLLOUT; 02586 02587 if (FD_ISSET (fdp->fd, &err_set)) 02588 fdp->revents |= _DBUS_POLLERR; 02589 } 02590 } 02591 02592 return ready; 02593 #endif 02594 } 02595 02603 void 02604 _dbus_get_monotonic_time (long *tv_sec, 02605 long *tv_usec) 02606 { 02607 #ifdef HAVE_MONOTONIC_CLOCK 02608 struct timespec ts; 02609 clock_gettime (CLOCK_MONOTONIC, &ts); 02610 02611 if (tv_sec) 02612 *tv_sec = ts.tv_sec; 02613 if (tv_usec) 02614 *tv_usec = ts.tv_nsec / 1000; 02615 #else 02616 struct timeval t; 02617 02618 gettimeofday (&t, NULL); 02619 02620 if (tv_sec) 02621 *tv_sec = t.tv_sec; 02622 if (tv_usec) 02623 *tv_usec = t.tv_usec; 02624 #endif 02625 } 02626 02634 void 02635 _dbus_get_real_time (long *tv_sec, 02636 long *tv_usec) 02637 { 02638 struct timeval t; 02639 02640 gettimeofday (&t, NULL); 02641 02642 if (tv_sec) 02643 *tv_sec = t.tv_sec; 02644 if (tv_usec) 02645 *tv_usec = t.tv_usec; 02646 } 02647 02656 dbus_bool_t 02657 _dbus_create_directory (const DBusString *filename, 02658 DBusError *error) 02659 { 02660 const char *filename_c; 02661 02662 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02663 02664 filename_c = _dbus_string_get_const_data (filename); 02665 02666 if (mkdir (filename_c, 0700) < 0) 02667 { 02668 if (errno == EEXIST) 02669 return TRUE; 02670 02671 dbus_set_error (error, DBUS_ERROR_FAILED, 02672 "Failed to create directory %s: %s\n", 02673 filename_c, _dbus_strerror (errno)); 02674 return FALSE; 02675 } 02676 else 02677 return TRUE; 02678 } 02679 02690 dbus_bool_t 02691 _dbus_concat_dir_and_file (DBusString *dir, 02692 const DBusString *next_component) 02693 { 02694 dbus_bool_t dir_ends_in_slash; 02695 dbus_bool_t file_starts_with_slash; 02696 02697 if (_dbus_string_get_length (dir) == 0 || 02698 _dbus_string_get_length (next_component) == 0) 02699 return TRUE; 02700 02701 dir_ends_in_slash = '/' == _dbus_string_get_byte (dir, 02702 _dbus_string_get_length (dir) - 1); 02703 02704 file_starts_with_slash = '/' == _dbus_string_get_byte (next_component, 0); 02705 02706 if (dir_ends_in_slash && file_starts_with_slash) 02707 { 02708 _dbus_string_shorten (dir, 1); 02709 } 02710 else if (!(dir_ends_in_slash || file_starts_with_slash)) 02711 { 02712 if (!_dbus_string_append_byte (dir, '/')) 02713 return FALSE; 02714 } 02715 02716 return _dbus_string_copy (next_component, 0, dir, 02717 _dbus_string_get_length (dir)); 02718 } 02719 02721 #define NANOSECONDS_PER_SECOND 1000000000 02722 02723 #define MICROSECONDS_PER_SECOND 1000000 02724 02725 #define MILLISECONDS_PER_SECOND 1000 02726 02727 #define NANOSECONDS_PER_MILLISECOND 1000000 02728 02729 #define MICROSECONDS_PER_MILLISECOND 1000 02730 02735 void 02736 _dbus_sleep_milliseconds (int milliseconds) 02737 { 02738 #ifdef HAVE_NANOSLEEP 02739 struct timespec req; 02740 struct timespec rem; 02741 02742 req.tv_sec = milliseconds / MILLISECONDS_PER_SECOND; 02743 req.tv_nsec = (milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; 02744 rem.tv_sec = 0; 02745 rem.tv_nsec = 0; 02746 02747 while (nanosleep (&req, &rem) < 0 && errno == EINTR) 02748 req = rem; 02749 #elif defined (HAVE_USLEEP) 02750 usleep (milliseconds * MICROSECONDS_PER_MILLISECOND); 02751 #else /* ! HAVE_USLEEP */ 02752 sleep (MAX (milliseconds / 1000, 1)); 02753 #endif 02754 } 02755 02756 static dbus_bool_t 02757 _dbus_generate_pseudorandom_bytes (DBusString *str, 02758 int n_bytes) 02759 { 02760 int old_len; 02761 char *p; 02762 02763 old_len = _dbus_string_get_length (str); 02764 02765 if (!_dbus_string_lengthen (str, n_bytes)) 02766 return FALSE; 02767 02768 p = _dbus_string_get_data_len (str, old_len, n_bytes); 02769 02770 _dbus_generate_pseudorandom_bytes_buffer (p, n_bytes); 02771 02772 return TRUE; 02773 } 02774 02783 dbus_bool_t 02784 _dbus_generate_random_bytes (DBusString *str, 02785 int n_bytes) 02786 { 02787 int old_len; 02788 int fd; 02789 02790 /* FALSE return means "no memory", if it could 02791 * mean something else then we'd need to return 02792 * a DBusError. So we always fall back to pseudorandom 02793 * if the I/O fails. 02794 */ 02795 02796 old_len = _dbus_string_get_length (str); 02797 fd = -1; 02798 02799 /* note, urandom on linux will fall back to pseudorandom */ 02800 fd = open ("/dev/urandom", O_RDONLY); 02801 if (fd < 0) 02802 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02803 02804 _dbus_verbose ("/dev/urandom fd %d opened\n", fd); 02805 02806 if (_dbus_read (fd, str, n_bytes) != n_bytes) 02807 { 02808 _dbus_close (fd, NULL); 02809 _dbus_string_set_length (str, old_len); 02810 return _dbus_generate_pseudorandom_bytes (str, n_bytes); 02811 } 02812 02813 _dbus_verbose ("Read %d bytes from /dev/urandom\n", 02814 n_bytes); 02815 02816 _dbus_close (fd, NULL); 02817 02818 return TRUE; 02819 } 02820 02826 void 02827 _dbus_exit (int code) 02828 { 02829 _exit (code); 02830 } 02831 02840 const char* 02841 _dbus_strerror (int error_number) 02842 { 02843 const char *msg; 02844 02845 msg = strerror (error_number); 02846 if (msg == NULL) 02847 msg = "unknown"; 02848 02849 return msg; 02850 } 02851 02855 void 02856 _dbus_disable_sigpipe (void) 02857 { 02858 signal (SIGPIPE, SIG_IGN); 02859 } 02860 02868 void 02869 _dbus_fd_set_close_on_exec (intptr_t fd) 02870 { 02871 int val; 02872 02873 val = fcntl (fd, F_GETFD, 0); 02874 02875 if (val < 0) 02876 return; 02877 02878 val |= FD_CLOEXEC; 02879 02880 fcntl (fd, F_SETFD, val); 02881 } 02882 02890 dbus_bool_t 02891 _dbus_close (int fd, 02892 DBusError *error) 02893 { 02894 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02895 02896 again: 02897 if (close (fd) < 0) 02898 { 02899 if (errno == EINTR) 02900 goto again; 02901 02902 dbus_set_error (error, _dbus_error_from_errno (errno), 02903 "Could not close fd %d", fd); 02904 return FALSE; 02905 } 02906 02907 return TRUE; 02908 } 02909 02917 int 02918 _dbus_dup(int fd, 02919 DBusError *error) 02920 { 02921 int new_fd; 02922 02923 #ifdef F_DUPFD_CLOEXEC 02924 dbus_bool_t cloexec_done; 02925 02926 new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); 02927 cloexec_done = new_fd >= 0; 02928 02929 if (new_fd < 0 && errno == EINVAL) 02930 #endif 02931 { 02932 new_fd = fcntl(fd, F_DUPFD, 3); 02933 } 02934 02935 if (new_fd < 0) { 02936 02937 dbus_set_error (error, _dbus_error_from_errno (errno), 02938 "Could not duplicate fd %d", fd); 02939 return -1; 02940 } 02941 02942 #ifdef F_DUPFD_CLOEXEC 02943 if (!cloexec_done) 02944 #endif 02945 { 02946 _dbus_fd_set_close_on_exec(new_fd); 02947 } 02948 02949 return new_fd; 02950 } 02951 02959 dbus_bool_t 02960 _dbus_set_fd_nonblocking (int fd, 02961 DBusError *error) 02962 { 02963 int val; 02964 02965 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 02966 02967 val = fcntl (fd, F_GETFL, 0); 02968 if (val < 0) 02969 { 02970 dbus_set_error (error, _dbus_error_from_errno (errno), 02971 "Failed to get flags from file descriptor %d: %s", 02972 fd, _dbus_strerror (errno)); 02973 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 02974 _dbus_strerror (errno)); 02975 return FALSE; 02976 } 02977 02978 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 02979 { 02980 dbus_set_error (error, _dbus_error_from_errno (errno), 02981 "Failed to set nonblocking flag of file descriptor %d: %s", 02982 fd, _dbus_strerror (errno)); 02983 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 02984 fd, _dbus_strerror (errno)); 02985 02986 return FALSE; 02987 } 02988 02989 return TRUE; 02990 } 02991 02997 void 02998 _dbus_print_backtrace (void) 02999 { 03000 #if defined (HAVE_BACKTRACE) && defined (DBUS_BUILT_R_DYNAMIC) 03001 void *bt[500]; 03002 int bt_size; 03003 int i; 03004 char **syms; 03005 03006 bt_size = backtrace (bt, 500); 03007 03008 syms = backtrace_symbols (bt, bt_size); 03009 03010 i = 0; 03011 while (i < bt_size) 03012 { 03013 /* don't use dbus_warn since it can _dbus_abort() */ 03014 fprintf (stderr, " %s\n", syms[i]); 03015 ++i; 03016 } 03017 fflush (stderr); 03018 03019 free (syms); 03020 #elif defined (HAVE_BACKTRACE) && ! defined (DBUS_BUILT_R_DYNAMIC) 03021 fprintf (stderr, " D-Bus not built with -rdynamic so unable to print a backtrace\n"); 03022 #else 03023 fprintf (stderr, " D-Bus not compiled with backtrace support so unable to print a backtrace\n"); 03024 #endif 03025 } 03026 03039 dbus_bool_t 03040 _dbus_full_duplex_pipe (int *fd1, 03041 int *fd2, 03042 dbus_bool_t blocking, 03043 DBusError *error) 03044 { 03045 #ifdef HAVE_SOCKETPAIR 03046 int fds[2]; 03047 int retval; 03048 03049 #ifdef SOCK_CLOEXEC 03050 dbus_bool_t cloexec_done; 03051 03052 retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds); 03053 cloexec_done = retval >= 0; 03054 03055 if (retval < 0 && errno == EINVAL) 03056 #endif 03057 { 03058 retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); 03059 } 03060 03061 if (retval < 0) 03062 { 03063 dbus_set_error (error, _dbus_error_from_errno (errno), 03064 "Could not create full-duplex pipe"); 03065 return FALSE; 03066 } 03067 03068 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03069 03070 #ifdef SOCK_CLOEXEC 03071 if (!cloexec_done) 03072 #endif 03073 { 03074 _dbus_fd_set_close_on_exec (fds[0]); 03075 _dbus_fd_set_close_on_exec (fds[1]); 03076 } 03077 03078 if (!blocking && 03079 (!_dbus_set_fd_nonblocking (fds[0], NULL) || 03080 !_dbus_set_fd_nonblocking (fds[1], NULL))) 03081 { 03082 dbus_set_error (error, _dbus_error_from_errno (errno), 03083 "Could not set full-duplex pipe nonblocking"); 03084 03085 _dbus_close (fds[0], NULL); 03086 _dbus_close (fds[1], NULL); 03087 03088 return FALSE; 03089 } 03090 03091 *fd1 = fds[0]; 03092 *fd2 = fds[1]; 03093 03094 _dbus_verbose ("full-duplex pipe %d <-> %d\n", 03095 *fd1, *fd2); 03096 03097 return TRUE; 03098 #else 03099 _dbus_warn ("_dbus_full_duplex_pipe() not implemented on this OS\n"); 03100 dbus_set_error (error, DBUS_ERROR_FAILED, 03101 "_dbus_full_duplex_pipe() not implemented on this OS"); 03102 return FALSE; 03103 #endif 03104 } 03105 03114 int 03115 _dbus_printf_string_upper_bound (const char *format, 03116 va_list args) 03117 { 03118 char static_buf[1024]; 03119 int bufsize = sizeof (static_buf); 03120 int len; 03121 03122 len = vsnprintf (static_buf, bufsize, format, args); 03123 03124 /* If vsnprintf() returned non-negative, then either the string fits in 03125 * static_buf, or this OS has the POSIX and C99 behaviour where vsnprintf 03126 * returns the number of characters that were needed, or this OS returns the 03127 * truncated length. 03128 * 03129 * We ignore the possibility that snprintf might just ignore the length and 03130 * overrun the buffer (64-bit Solaris 7), because that's pathological. 03131 * If your libc is really that bad, come back when you have a better one. */ 03132 if (len == bufsize) 03133 { 03134 /* This could be the truncated length (Tru64 and IRIX have this bug), 03135 * or the real length could be coincidentally the same. Which is it? 03136 * If vsnprintf returns the truncated length, we'll go to the slow 03137 * path. */ 03138 if (vsnprintf (static_buf, 1, format, args) == 1) 03139 len = -1; 03140 } 03141 03142 /* If vsnprintf() returned negative, we have to do more work. 03143 * HP-UX returns negative. */ 03144 while (len < 0) 03145 { 03146 char *buf; 03147 03148 bufsize *= 2; 03149 03150 buf = dbus_malloc (bufsize); 03151 03152 if (buf == NULL) 03153 return -1; 03154 03155 len = vsnprintf (buf, bufsize, format, args); 03156 dbus_free (buf); 03157 03158 /* If the reported length is exactly the buffer size, round up to the 03159 * next size, in case vsnprintf has been returning the truncated 03160 * length */ 03161 if (len == bufsize) 03162 len = -1; 03163 } 03164 03165 return len; 03166 } 03167 03174 const char* 03175 _dbus_get_tmpdir(void) 03176 { 03177 static const char* tmpdir = NULL; 03178 03179 if (tmpdir == NULL) 03180 { 03181 /* TMPDIR is what glibc uses, then 03182 * glibc falls back to the P_tmpdir macro which 03183 * just expands to "/tmp" 03184 */ 03185 if (tmpdir == NULL) 03186 tmpdir = getenv("TMPDIR"); 03187 03188 /* These two env variables are probably 03189 * broken, but maybe some OS uses them? 03190 */ 03191 if (tmpdir == NULL) 03192 tmpdir = getenv("TMP"); 03193 if (tmpdir == NULL) 03194 tmpdir = getenv("TEMP"); 03195 03196 /* And this is the sane fallback. */ 03197 if (tmpdir == NULL) 03198 tmpdir = "/tmp"; 03199 } 03200 03201 _dbus_assert(tmpdir != NULL); 03202 03203 return tmpdir; 03204 } 03205 03225 static dbus_bool_t 03226 _read_subprocess_line_argv (const char *progpath, 03227 dbus_bool_t path_fallback, 03228 char * const *argv, 03229 DBusString *result, 03230 DBusError *error) 03231 { 03232 int result_pipe[2] = { -1, -1 }; 03233 int errors_pipe[2] = { -1, -1 }; 03234 pid_t pid; 03235 int ret; 03236 int status; 03237 int orig_len; 03238 03239 dbus_bool_t retval; 03240 sigset_t new_set, old_set; 03241 03242 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03243 retval = FALSE; 03244 03245 /* We need to block any existing handlers for SIGCHLD temporarily; they 03246 * will cause waitpid() below to fail. 03247 * https://bugs.freedesktop.org/show_bug.cgi?id=21347 03248 */ 03249 sigemptyset (&new_set); 03250 sigaddset (&new_set, SIGCHLD); 03251 sigprocmask (SIG_BLOCK, &new_set, &old_set); 03252 03253 orig_len = _dbus_string_get_length (result); 03254 03255 #define READ_END 0 03256 #define WRITE_END 1 03257 if (pipe (result_pipe) < 0) 03258 { 03259 dbus_set_error (error, _dbus_error_from_errno (errno), 03260 "Failed to create a pipe to call %s: %s", 03261 progpath, _dbus_strerror (errno)); 03262 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03263 progpath, _dbus_strerror (errno)); 03264 goto out; 03265 } 03266 if (pipe (errors_pipe) < 0) 03267 { 03268 dbus_set_error (error, _dbus_error_from_errno (errno), 03269 "Failed to create a pipe to call %s: %s", 03270 progpath, _dbus_strerror (errno)); 03271 _dbus_verbose ("Failed to create a pipe to call %s: %s\n", 03272 progpath, _dbus_strerror (errno)); 03273 goto out; 03274 } 03275 03276 pid = fork (); 03277 if (pid < 0) 03278 { 03279 dbus_set_error (error, _dbus_error_from_errno (errno), 03280 "Failed to fork() to call %s: %s", 03281 progpath, _dbus_strerror (errno)); 03282 _dbus_verbose ("Failed to fork() to call %s: %s\n", 03283 progpath, _dbus_strerror (errno)); 03284 goto out; 03285 } 03286 03287 if (pid == 0) 03288 { 03289 /* child process */ 03290 int fd; 03291 03292 fd = open ("/dev/null", O_RDWR); 03293 if (fd == -1) 03294 /* huh?! can't open /dev/null? */ 03295 _exit (1); 03296 03297 _dbus_verbose ("/dev/null fd %d opened\n", fd); 03298 03299 /* set-up stdXXX */ 03300 close (result_pipe[READ_END]); 03301 close (errors_pipe[READ_END]); 03302 close (0); /* close stdin */ 03303 close (1); /* close stdout */ 03304 close (2); /* close stderr */ 03305 03306 if (dup2 (fd, 0) == -1) 03307 _exit (1); 03308 if (dup2 (result_pipe[WRITE_END], 1) == -1) 03309 _exit (1); 03310 if (dup2 (errors_pipe[WRITE_END], 2) == -1) 03311 _exit (1); 03312 03313 _dbus_close_all (); 03314 03315 sigprocmask (SIG_SETMASK, &old_set, NULL); 03316 03317 /* If it looks fully-qualified, try execv first */ 03318 if (progpath[0] == '/') 03319 { 03320 execv (progpath, argv); 03321 /* Ok, that failed. Now if path_fallback is given, let's 03322 * try unqualified. This is mostly a hack to work 03323 * around systems which ship dbus-launch in /usr/bin 03324 * but everything else in /bin (because dbus-launch 03325 * depends on X11). 03326 */ 03327 if (path_fallback) 03328 /* We must have a slash, because we checked above */ 03329 execvp (strrchr (progpath, '/')+1, argv); 03330 } 03331 else 03332 execvp (progpath, argv); 03333 03334 /* still nothing, we failed */ 03335 _exit (1); 03336 } 03337 03338 /* parent process */ 03339 close (result_pipe[WRITE_END]); 03340 close (errors_pipe[WRITE_END]); 03341 result_pipe[WRITE_END] = -1; 03342 errors_pipe[WRITE_END] = -1; 03343 03344 ret = 0; 03345 do 03346 { 03347 ret = _dbus_read (result_pipe[READ_END], result, 1024); 03348 } 03349 while (ret > 0); 03350 03351 /* reap the child process to avoid it lingering as zombie */ 03352 do 03353 { 03354 ret = waitpid (pid, &status, 0); 03355 } 03356 while (ret == -1 && errno == EINTR); 03357 03358 /* We succeeded if the process exited with status 0 and 03359 anything was read */ 03360 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0 ) 03361 { 03362 /* The process ended with error */ 03363 DBusString error_message; 03364 if (!_dbus_string_init (&error_message)) 03365 { 03366 _DBUS_SET_OOM (error); 03367 goto out; 03368 } 03369 03370 ret = 0; 03371 do 03372 { 03373 ret = _dbus_read (errors_pipe[READ_END], &error_message, 1024); 03374 } 03375 while (ret > 0); 03376 03377 _dbus_string_set_length (result, orig_len); 03378 if (_dbus_string_get_length (&error_message) > 0) 03379 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03380 "%s terminated abnormally with the following error: %s", 03381 progpath, _dbus_string_get_data (&error_message)); 03382 else 03383 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 03384 "%s terminated abnormally without any error message", 03385 progpath); 03386 goto out; 03387 } 03388 03389 retval = TRUE; 03390 03391 out: 03392 sigprocmask (SIG_SETMASK, &old_set, NULL); 03393 03394 if (retval) 03395 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03396 else 03397 _DBUS_ASSERT_ERROR_IS_SET (error); 03398 03399 if (result_pipe[0] != -1) 03400 close (result_pipe[0]); 03401 if (result_pipe[1] != -1) 03402 close (result_pipe[1]); 03403 if (errors_pipe[0] != -1) 03404 close (errors_pipe[0]); 03405 if (errors_pipe[1] != -1) 03406 close (errors_pipe[1]); 03407 03408 return retval; 03409 } 03410 03422 dbus_bool_t 03423 _dbus_get_autolaunch_address (const char *scope, 03424 DBusString *address, 03425 DBusError *error) 03426 { 03427 #ifdef DBUS_ENABLE_X11_AUTOLAUNCH 03428 /* Perform X11-based autolaunch. (We also support launchd-based autolaunch, 03429 * but that's done elsewhere, and if it worked, this function wouldn't 03430 * be called.) */ 03431 const char *display; 03432 static char *argv[6]; 03433 int i; 03434 DBusString uuid; 03435 dbus_bool_t retval; 03436 03437 if (_dbus_check_setuid ()) 03438 { 03439 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03440 "Unable to autolaunch when setuid"); 03441 return FALSE; 03442 } 03443 03444 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03445 retval = FALSE; 03446 03447 /* fd.o #19997: if $DISPLAY isn't set to something useful, then 03448 * dbus-launch-x11 is just going to fail. Rather than trying to 03449 * run it, we might as well bail out early with a nice error. */ 03450 display = _dbus_getenv ("DISPLAY"); 03451 03452 if (display == NULL || display[0] == '\0') 03453 { 03454 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03455 "Unable to autolaunch a dbus-daemon without a $DISPLAY for X11"); 03456 return FALSE; 03457 } 03458 03459 if (!_dbus_string_init (&uuid)) 03460 { 03461 _DBUS_SET_OOM (error); 03462 return FALSE; 03463 } 03464 03465 if (!_dbus_get_local_machine_uuid_encoded (&uuid)) 03466 { 03467 _DBUS_SET_OOM (error); 03468 goto out; 03469 } 03470 03471 i = 0; 03472 argv[i] = "dbus-launch"; 03473 ++i; 03474 argv[i] = "--autolaunch"; 03475 ++i; 03476 argv[i] = _dbus_string_get_data (&uuid); 03477 ++i; 03478 argv[i] = "--binary-syntax"; 03479 ++i; 03480 argv[i] = "--close-stderr"; 03481 ++i; 03482 argv[i] = NULL; 03483 ++i; 03484 03485 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03486 03487 retval = _read_subprocess_line_argv (DBUS_BINDIR "/dbus-launch", 03488 TRUE, 03489 argv, address, error); 03490 03491 out: 03492 _dbus_string_free (&uuid); 03493 return retval; 03494 #else 03495 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03496 "Using X11 for dbus-daemon autolaunch was disabled at compile time, " 03497 "set your DBUS_SESSION_BUS_ADDRESS instead"); 03498 return FALSE; 03499 #endif 03500 } 03501 03520 dbus_bool_t 03521 _dbus_read_local_machine_uuid (DBusGUID *machine_id, 03522 dbus_bool_t create_if_not_found, 03523 DBusError *error) 03524 { 03525 DBusString filename; 03526 dbus_bool_t b; 03527 03528 _dbus_string_init_const (&filename, DBUS_MACHINE_UUID_FILE); 03529 03530 b = _dbus_read_uuid_file (&filename, machine_id, create_if_not_found, error); 03531 if (b) 03532 return TRUE; 03533 03534 dbus_error_free (error); 03535 03536 /* Fallback to the system machine ID */ 03537 _dbus_string_init_const (&filename, "/etc/machine-id"); 03538 return _dbus_read_uuid_file (&filename, machine_id, FALSE, error); 03539 } 03540 03541 #define DBUS_UNIX_STANDARD_SESSION_SERVICEDIR "/dbus-1/services" 03542 #define DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR "/dbus-1/system-services" 03543 03550 dbus_bool_t 03551 _dbus_lookup_launchd_socket (DBusString *socket_path, 03552 const char *launchd_env_var, 03553 DBusError *error) 03554 { 03555 #ifdef DBUS_ENABLE_LAUNCHD 03556 char *argv[4]; 03557 int i; 03558 03559 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03560 03561 if (_dbus_check_setuid ()) 03562 { 03563 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03564 "Unable to find launchd socket when setuid"); 03565 return FALSE; 03566 } 03567 03568 i = 0; 03569 argv[i] = "launchctl"; 03570 ++i; 03571 argv[i] = "getenv"; 03572 ++i; 03573 argv[i] = (char*)launchd_env_var; 03574 ++i; 03575 argv[i] = NULL; 03576 ++i; 03577 03578 _dbus_assert (i == _DBUS_N_ELEMENTS (argv)); 03579 03580 if (!_read_subprocess_line_argv(argv[0], TRUE, argv, socket_path, error)) 03581 { 03582 return FALSE; 03583 } 03584 03585 /* no error, but no result either */ 03586 if (_dbus_string_get_length(socket_path) == 0) 03587 { 03588 return FALSE; 03589 } 03590 03591 /* strip the carriage-return */ 03592 _dbus_string_shorten(socket_path, 1); 03593 return TRUE; 03594 #else /* DBUS_ENABLE_LAUNCHD */ 03595 dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED, 03596 "can't lookup socket from launchd; launchd support not compiled in"); 03597 return FALSE; 03598 #endif 03599 } 03600 03601 #ifdef DBUS_ENABLE_LAUNCHD 03602 static dbus_bool_t 03603 _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) 03604 { 03605 dbus_bool_t valid_socket; 03606 DBusString socket_path; 03607 03608 if (_dbus_check_setuid ()) 03609 { 03610 dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, 03611 "Unable to find launchd socket when setuid"); 03612 return FALSE; 03613 } 03614 03615 if (!_dbus_string_init (&socket_path)) 03616 { 03617 _DBUS_SET_OOM (error); 03618 return FALSE; 03619 } 03620 03621 valid_socket = _dbus_lookup_launchd_socket (&socket_path, "DBUS_LAUNCHD_SESSION_BUS_SOCKET", error); 03622 03623 if (dbus_error_is_set(error)) 03624 { 03625 _dbus_string_free(&socket_path); 03626 return FALSE; 03627 } 03628 03629 if (!valid_socket) 03630 { 03631 dbus_set_error(error, "no socket path", 03632 "launchd did not provide a socket path, " 03633 "verify that org.freedesktop.dbus-session.plist is loaded!"); 03634 _dbus_string_free(&socket_path); 03635 return FALSE; 03636 } 03637 if (!_dbus_string_append (address, "unix:path=")) 03638 { 03639 _DBUS_SET_OOM (error); 03640 _dbus_string_free(&socket_path); 03641 return FALSE; 03642 } 03643 if (!_dbus_string_copy (&socket_path, 0, address, 03644 _dbus_string_get_length (address))) 03645 { 03646 _DBUS_SET_OOM (error); 03647 _dbus_string_free(&socket_path); 03648 return FALSE; 03649 } 03650 03651 _dbus_string_free(&socket_path); 03652 return TRUE; 03653 } 03654 #endif 03655 03675 dbus_bool_t 03676 _dbus_lookup_session_address (dbus_bool_t *supported, 03677 DBusString *address, 03678 DBusError *error) 03679 { 03680 #ifdef DBUS_ENABLE_LAUNCHD 03681 *supported = TRUE; 03682 return _dbus_lookup_session_address_launchd (address, error); 03683 #else 03684 /* On non-Mac Unix platforms, if the session address isn't already 03685 * set in DBUS_SESSION_BUS_ADDRESS environment variable, we punt and 03686 * fall back to the autolaunch: global default; see 03687 * init_session_address in dbus/dbus-bus.c. */ 03688 *supported = FALSE; 03689 return TRUE; 03690 #endif 03691 } 03692 03710 dbus_bool_t 03711 _dbus_get_standard_session_servicedirs (DBusList **dirs) 03712 { 03713 const char *xdg_data_home; 03714 const char *xdg_data_dirs; 03715 DBusString servicedir_path; 03716 03717 if (!_dbus_string_init (&servicedir_path)) 03718 return FALSE; 03719 03720 xdg_data_home = _dbus_getenv ("XDG_DATA_HOME"); 03721 xdg_data_dirs = _dbus_getenv ("XDG_DATA_DIRS"); 03722 03723 if (xdg_data_home != NULL) 03724 { 03725 if (!_dbus_string_append (&servicedir_path, xdg_data_home)) 03726 goto oom; 03727 } 03728 else 03729 { 03730 const DBusString *homedir; 03731 DBusString local_share; 03732 03733 if (!_dbus_homedir_from_current_process (&homedir)) 03734 goto oom; 03735 03736 if (!_dbus_string_append (&servicedir_path, _dbus_string_get_const_data (homedir))) 03737 goto oom; 03738 03739 _dbus_string_init_const (&local_share, "/.local/share"); 03740 if (!_dbus_concat_dir_and_file (&servicedir_path, &local_share)) 03741 goto oom; 03742 } 03743 03744 if (!_dbus_string_append (&servicedir_path, ":")) 03745 goto oom; 03746 03747 if (xdg_data_dirs != NULL) 03748 { 03749 if (!_dbus_string_append (&servicedir_path, xdg_data_dirs)) 03750 goto oom; 03751 03752 if (!_dbus_string_append (&servicedir_path, ":")) 03753 goto oom; 03754 } 03755 else 03756 { 03757 if (!_dbus_string_append (&servicedir_path, "/usr/local/share:/usr/share:")) 03758 goto oom; 03759 } 03760 03761 /* 03762 * add configured datadir to defaults 03763 * this may be the same as an xdg dir 03764 * however the config parser should take 03765 * care of duplicates 03766 */ 03767 if (!_dbus_string_append (&servicedir_path, DBUS_DATADIR)) 03768 goto oom; 03769 03770 if (!_dbus_split_paths_and_append (&servicedir_path, 03771 DBUS_UNIX_STANDARD_SESSION_SERVICEDIR, 03772 dirs)) 03773 goto oom; 03774 03775 _dbus_string_free (&servicedir_path); 03776 return TRUE; 03777 03778 oom: 03779 _dbus_string_free (&servicedir_path); 03780 return FALSE; 03781 } 03782 03783 03802 dbus_bool_t 03803 _dbus_get_standard_system_servicedirs (DBusList **dirs) 03804 { 03805 /* 03806 * DBUS_DATADIR may be the same as one of the standard directories. However, 03807 * the config parser should take care of the duplicates. 03808 * 03809 * Also, append /lib as counterpart of /usr/share on the root 03810 * directory (the root directory does not know /share), in order to 03811 * facilitate early boot system bus activation where /usr might not 03812 * be available. 03813 */ 03814 static const char standard_search_path[] = 03815 "/usr/local/share:" 03816 "/usr/share:" 03817 DBUS_DATADIR ":" 03818 "/lib"; 03819 DBusString servicedir_path; 03820 03821 _dbus_string_init_const (&servicedir_path, standard_search_path); 03822 03823 return _dbus_split_paths_and_append (&servicedir_path, 03824 DBUS_UNIX_STANDARD_SYSTEM_SERVICEDIR, 03825 dirs); 03826 } 03827 03836 dbus_bool_t 03837 _dbus_append_system_config_file (DBusString *str) 03838 { 03839 return _dbus_string_append (str, DBUS_SYSTEM_CONFIG_FILE); 03840 } 03841 03848 dbus_bool_t 03849 _dbus_append_session_config_file (DBusString *str) 03850 { 03851 return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); 03852 } 03853 03861 void 03862 _dbus_flush_caches (void) 03863 { 03864 _dbus_user_database_flush_system (); 03865 } 03866 03880 dbus_bool_t 03881 _dbus_append_keyring_directory_for_credentials (DBusString *directory, 03882 DBusCredentials *credentials) 03883 { 03884 DBusString homedir; 03885 DBusString dotdir; 03886 dbus_uid_t uid; 03887 03888 _dbus_assert (credentials != NULL); 03889 _dbus_assert (!_dbus_credentials_are_anonymous (credentials)); 03890 03891 if (!_dbus_string_init (&homedir)) 03892 return FALSE; 03893 03894 uid = _dbus_credentials_get_unix_uid (credentials); 03895 _dbus_assert (uid != DBUS_UID_UNSET); 03896 03897 if (!_dbus_homedir_from_uid (uid, &homedir)) 03898 goto failed; 03899 03900 #ifdef DBUS_BUILD_TESTS 03901 { 03902 const char *override; 03903 03904 override = _dbus_getenv ("DBUS_TEST_HOMEDIR"); 03905 if (override != NULL && *override != '\0') 03906 { 03907 _dbus_string_set_length (&homedir, 0); 03908 if (!_dbus_string_append (&homedir, override)) 03909 goto failed; 03910 03911 _dbus_verbose ("Using fake homedir for testing: %s\n", 03912 _dbus_string_get_const_data (&homedir)); 03913 } 03914 else 03915 { 03916 static dbus_bool_t already_warned = FALSE; 03917 if (!already_warned) 03918 { 03919 _dbus_warn ("Using your real home directory for testing, set DBUS_TEST_HOMEDIR to avoid\n"); 03920 already_warned = TRUE; 03921 } 03922 } 03923 } 03924 #endif 03925 03926 _dbus_string_init_const (&dotdir, ".dbus-keyrings"); 03927 if (!_dbus_concat_dir_and_file (&homedir, 03928 &dotdir)) 03929 goto failed; 03930 03931 if (!_dbus_string_copy (&homedir, 0, 03932 directory, _dbus_string_get_length (directory))) { 03933 goto failed; 03934 } 03935 03936 _dbus_string_free (&homedir); 03937 return TRUE; 03938 03939 failed: 03940 _dbus_string_free (&homedir); 03941 return FALSE; 03942 } 03943 03944 //PENDING(kdab) docs 03945 dbus_bool_t 03946 _dbus_daemon_publish_session_bus_address (const char* addr, 03947 const char *scope) 03948 { 03949 return TRUE; 03950 } 03951 03952 //PENDING(kdab) docs 03953 void 03954 _dbus_daemon_unpublish_session_bus_address (void) 03955 { 03956 03957 } 03958 03965 dbus_bool_t 03966 _dbus_get_is_errno_eagain_or_ewouldblock (void) 03967 { 03968 return errno == EAGAIN || errno == EWOULDBLOCK; 03969 } 03970 03978 dbus_bool_t 03979 _dbus_delete_directory (const DBusString *filename, 03980 DBusError *error) 03981 { 03982 const char *filename_c; 03983 03984 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 03985 03986 filename_c = _dbus_string_get_const_data (filename); 03987 03988 if (rmdir (filename_c) != 0) 03989 { 03990 dbus_set_error (error, DBUS_ERROR_FAILED, 03991 "Failed to remove directory %s: %s\n", 03992 filename_c, _dbus_strerror (errno)); 03993 return FALSE; 03994 } 03995 03996 return TRUE; 03997 } 03998 04006 dbus_bool_t 04007 _dbus_socket_can_pass_unix_fd(int fd) { 04008 04009 #ifdef SCM_RIGHTS 04010 union { 04011 struct sockaddr sa; 04012 struct sockaddr_storage storage; 04013 struct sockaddr_un un; 04014 } sa_buf; 04015 04016 socklen_t sa_len = sizeof(sa_buf); 04017 04018 _DBUS_ZERO(sa_buf); 04019 04020 if (getsockname(fd, &sa_buf.sa, &sa_len) < 0) 04021 return FALSE; 04022 04023 return sa_buf.sa.sa_family == AF_UNIX; 04024 04025 #else 04026 return FALSE; 04027 04028 #endif 04029 } 04030 04031 04032 /* 04033 * replaces the term DBUS_PREFIX in configure_time_path by the 04034 * current dbus installation directory. On unix this function is a noop 04035 * 04036 * @param configure_time_path 04037 * @return real path 04038 */ 04039 const char * 04040 _dbus_replace_install_prefix (const char *configure_time_path) 04041 { 04042 return configure_time_path; 04043 } 04044 04049 void 04050 _dbus_close_all (void) 04051 { 04052 int maxfds, i; 04053 04054 #ifdef __linux__ 04055 DIR *d; 04056 04057 /* On Linux we can optimize this a bit if /proc is available. If it 04058 isn't available, fall back to the brute force way. */ 04059 04060 d = opendir ("/proc/self/fd"); 04061 if (d) 04062 { 04063 for (;;) 04064 { 04065 struct dirent buf, *de; 04066 int k, fd; 04067 long l; 04068 char *e = NULL; 04069 04070 k = readdir_r (d, &buf, &de); 04071 if (k != 0 || !de) 04072 break; 04073 04074 if (de->d_name[0] == '.') 04075 continue; 04076 04077 errno = 0; 04078 l = strtol (de->d_name, &e, 10); 04079 if (errno != 0 || e == NULL || *e != '\0') 04080 continue; 04081 04082 fd = (int) l; 04083 if (fd < 3) 04084 continue; 04085 04086 if (fd == dirfd (d)) 04087 continue; 04088 04089 close (fd); 04090 } 04091 04092 closedir (d); 04093 return; 04094 } 04095 #endif 04096 04097 maxfds = sysconf (_SC_OPEN_MAX); 04098 04099 /* Pick something reasonable if for some reason sysconf says 04100 * unlimited. 04101 */ 04102 if (maxfds < 0) 04103 maxfds = 1024; 04104 04105 /* close all inherited fds */ 04106 for (i = 3; i < maxfds; i++) 04107 close (i); 04108 } 04109 04119 dbus_bool_t 04120 _dbus_check_setuid (void) 04121 { 04122 /* TODO: get __libc_enable_secure exported from glibc. 04123 * See http://www.openwall.com/lists/owl-dev/2012/08/14/1 04124 */ 04125 #if 0 && defined(HAVE_LIBC_ENABLE_SECURE) 04126 { 04127 /* See glibc/include/unistd.h */ 04128 extern int __libc_enable_secure; 04129 return __libc_enable_secure; 04130 } 04131 #elif defined(HAVE_ISSETUGID) 04132 /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */ 04133 return issetugid (); 04134 #else 04135 uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ 04136 gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ 04137 04138 static dbus_bool_t check_setuid_initialised; 04139 static dbus_bool_t is_setuid; 04140 04141 if (_DBUS_UNLIKELY (!check_setuid_initialised)) 04142 { 04143 #ifdef HAVE_GETRESUID 04144 if (getresuid (&ruid, &euid, &suid) != 0 || 04145 getresgid (&rgid, &egid, &sgid) != 0) 04146 #endif /* HAVE_GETRESUID */ 04147 { 04148 suid = ruid = getuid (); 04149 sgid = rgid = getgid (); 04150 euid = geteuid (); 04151 egid = getegid (); 04152 } 04153 04154 check_setuid_initialised = TRUE; 04155 is_setuid = (ruid != euid || ruid != suid || 04156 rgid != egid || rgid != sgid); 04157 04158 } 04159 return is_setuid; 04160 #endif 04161 } 04162 04163 /* tests in dbus-sysdeps-util.c */