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