diff options
author | Adrian Szyndela <adrian.s@samsung.com> | 2020-09-25 15:55:03 +0200 |
---|---|---|
committer | Adrian Szyndela <adrian.s@samsung.com> | 2020-09-25 15:55:03 +0200 |
commit | bd07233e6cb1224cfa61d9a06df9def4d6b6a24e (patch) | |
tree | 25a9a4f17684ae5323c78502e179f189ec8cdb4d | |
parent | 6a5aacd05f021ecd27fed8a9b2432d7f031ad3c2 (diff) | |
parent | ab88811768f750777d1a8b9d9ab12f13390bfd3a (diff) | |
download | dbus-bd07233e6cb1224cfa61d9a06df9def4d6b6a24e.tar.gz dbus-bd07233e6cb1224cfa61d9a06df9def4d6b6a24e.tar.bz2 dbus-bd07233e6cb1224cfa61d9a06df9def4d6b6a24e.zip |
Merge 'dbus-1.12.20' into tizen
dbus-1.12.20
Change-Id: I8b3a9e851dca1d42a5785fa94c97f5e9074cac35
-rw-r--r-- | NEWS | 63 | ||||
-rw-r--r-- | bus/connection.c | 7 | ||||
-rw-r--r-- | cmake/tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | dbus/dbus-message.c | 14 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 53 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.h | 2 | ||||
-rw-r--r-- | dbus/dbus-userdb-util.c | 44 | ||||
-rw-r--r-- | dbus/dbus-userdb.c | 73 | ||||
-rw-r--r-- | dbus/dbus-userdb.h | 16 | ||||
-rw-r--r-- | doc/dbus-daemon.1.xml.in | 2 | ||||
-rw-r--r-- | doc/dbus-send.1.xml.in | 12 | ||||
-rw-r--r-- | test/dbus-daemon.c | 30 | ||||
-rw-r--r-- | test/fdpass.c | 14 |
14 files changed, 271 insertions, 64 deletions
@@ -1,3 +1,66 @@ +dbus 1.12.20 (2020-07-02) +========================= + +The “temporary nemesis” release. + +Maybe security fixes: + +• On Unix, avoid a use-after-free if two usernames have the same + numeric uid. In older versions this could lead to a crash (denial of + service) or other undefined behaviour, possibly including incorrect + authorization decisions if <policy group=...> is used. + Like Unix filesystems, D-Bus' model of identity cannot distinguish + between users of different names with the same numeric uid, so this + configuration is not advisable on systems where D-Bus will be used. + Thanks to Daniel Onaca. + (dbus#305, dbus!166; Simon McVittie) + +Other fixes: + +• On Solaris and its derivatives, if a cmsg header is truncated, ensure + that we do not overrun the buffer used for fd-passing, even if the + kernel tells us to. + (dbus#304, dbus!165; Andy Fiddaman) + +dbus 1.12.18 (2020-06-02) +========================= + +The “telepathic vines” release. + +Denial of service fixes: + +• CVE-2020-12049: If a message contains more file descriptors than can + be sent, close those that did get through before reporting error. + Previously, a local attacker could cause the system dbus-daemon (or + another system service with its own DBusServer) to run out of file + descriptors, by repeatedly connecting to the server and sending fds that + would get leaked. + Thanks to Kevin Backhouse of GitHub Security Lab. + (dbus#294, GHSL-2020-057; Simon McVittie) + +Other fixes: + +• Fix a crash when the dbus-daemon is terminated while one or more + monitors are active (dbus#291, dbus!140; Simon McVittie) + +• The dbus-send(1) man page now documents --bus and --peer instead of + the old --address synonym for --peer, which has been deprecated since + the introduction of --bus and --peer in 1.7.6 + (fd.o #48816, dbus!115; Chris Morin) + +• Fix a wrong environment variable name in dbus-daemon(1) + (dbus#275, dbus!122; Mubin, Philip Withnall) + +• Fix formatting of dbus_message_append_args example + (dbus!126, Felipe Franciosi) + +• Avoid a test failure on Linux when built in a container as uid 0, but + without the necessary privileges to increase resource limits + (dbus!58, Debian #908092; Simon McVittie) + +• When building with CMake, cope with libX11 in a non-standard location + (dbus!129, Tuomo Rinne) + dbus 1.12.16 (2019-06-11) ========================= diff --git a/bus/connection.c b/bus/connection.c index 6b85ba37..78948c6c 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -555,9 +555,6 @@ bus_connections_unref (BusConnections *connections) _dbus_assert (connections->n_incomplete == 0); - /* drop all monitors */ - _dbus_list_clear (&connections->monitors); - /* drop all real connections */ while (connections->completed != NULL) { @@ -573,6 +570,10 @@ bus_connections_unref (BusConnections *connections) _dbus_assert (connections->n_completed == 0); + /* disconnecting all the connections should have emptied the list of + * monitors (each link is removed in bus_connection_disconnected) */ + _dbus_assert (connections->monitors == NULL); + bus_expire_list_free (connections->pending_replies); _dbus_loop_remove_timeout (bus_context_get_loop (connections->context), diff --git a/cmake/tools/CMakeLists.txt b/cmake/tools/CMakeLists.txt index c05ced43..4678bddf 100644 --- a/cmake/tools/CMakeLists.txt +++ b/cmake/tools/CMakeLists.txt @@ -48,6 +48,7 @@ set (dbus_launch_SOURCES ${dbus_launch_SOURCES} ../../tools/dbus-launch-x11.c ) +include_directories(${X11_INCLUDE_DIR}) endif(DBUS_BUILD_X11) set (dbus_cleanup_sockets_SOURCES diff --git a/configure.ac b/configure.ac index e7d8d38b..20c821ac 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.63]) m4_define([dbus_major_version], [1]) m4_define([dbus_minor_version], [12]) -m4_define([dbus_micro_version], [16]) +m4_define([dbus_micro_version], [20]) m4_define([dbus_version], [dbus_major_version.dbus_minor_version.dbus_micro_version]) AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus]) @@ -42,7 +42,7 @@ LT_CURRENT=22 ## increment any time the source changes; set to ## 0 if you increment CURRENT -LT_REVISION=11 +LT_REVISION=13 ## increment if any interfaces have been added; set to 0 ## if any interfaces have been changed or removed. removal has diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 7fec3131..7d44a2e4 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -1954,10 +1954,16 @@ dbus_message_get_type (DBusMessage *message) * To append an array of fixed-length basic types (except Unix file * descriptors), pass in the DBUS_TYPE_ARRAY typecode, the element * typecode, the address of the array pointer, and a 32-bit integer - * giving the number of elements in the array. So for example: @code - * const dbus_int32_t array[] = { 1, 2, 3 }; const dbus_int32_t - * *v_ARRAY = array; dbus_message_append_args (message, - * DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3, DBUS_TYPE_INVALID); + * giving the number of elements in the array. So for example: + * + * @code + * + * const dbus_int32_t array[] = { 1, 2, 3 }; + * const dbus_int32_t *v_ARRAY = array; + * dbus_message_append_args (message, + * DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3, + * DBUS_TYPE_INVALID); + * * @endcode * * This function does not support arrays of Unix file descriptors. If diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index e8cd5b33..e511afc5 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -435,31 +435,38 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd, struct cmsghdr *cm; dbus_bool_t found = FALSE; - if (m.msg_flags & MSG_CTRUNC) - { - /* Hmm, apparently the control data was truncated. The bad - thing is that we might have completely lost a couple of fds - without chance to recover them. Hence let's treat this as a - serious error. */ - - errno = ENOSPC; - _dbus_string_set_length (buffer, start); - return -1; - } - for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm)) if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS) { size_t i; int *payload = (int *) CMSG_DATA (cm); size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0)); - size_t payload_len_fds = payload_len_bytes / sizeof (int); + size_t payload_len_fds; size_t fds_to_use; /* Every unsigned int fits in a size_t without truncation, so * casting (size_t) *n_fds is OK */ _DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (unsigned int)); + if ((m.msg_flags & MSG_CTRUNC) && CMSG_NXTHDR(&m, cm) == NULL && + (char *) payload + payload_len_bytes > + (char *) m.msg_control + m.msg_controllen) + { + /* This is the last cmsg in a truncated message and using + * cmsg_len would apparently overrun the allocated buffer. + * Some operating systems (illumos and Solaris are known) do + * not adjust cmsg_len in the last cmsg when truncation occurs. + * Adjust the payload length here. The calculation for + * payload_len_fds below will discard any trailing bytes that + * belong to an incomplete file descriptor - the kernel will + * have already closed that (at least for illumos and Solaris) + */ + payload_len_bytes = m.msg_controllen - + ((char *) payload - (char *) m.msg_control); + } + + payload_len_fds = payload_len_bytes / sizeof (int); + if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds)) { /* The fds in the payload will fit in our buffer */ @@ -501,6 +508,26 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd, if (!found) *n_fds = 0; + if (m.msg_flags & MSG_CTRUNC) + { + unsigned int i; + + /* Hmm, apparently the control data was truncated. The bad + thing is that we might have completely lost a couple of fds + without chance to recover them. Hence let's treat this as a + serious error. */ + + /* We still need to close whatever fds we *did* receive, + * otherwise they'll never get closed. (CVE-2020-12049) */ + for (i = 0; i < *n_fds; i++) + close (fds[i]); + + *n_fds = 0; + errno = ENOSPC; + _dbus_string_set_length (buffer, start); + return -1; + } + /* put length back (doesn't actually realloc) */ _dbus_string_set_length (buffer, start + bytes_read); diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 8d3df2d6..830d5cd0 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -105,6 +105,7 @@ typedef struct DBusGroupInfo DBusGroupInfo; */ struct DBusUserInfo { + size_t refcount; /**< Reference count */ dbus_uid_t uid; /**< UID */ dbus_gid_t primary_gid; /**< GID */ dbus_gid_t *group_ids; /**< Groups IDs, *including* above primary group */ @@ -118,6 +119,7 @@ struct DBusUserInfo */ struct DBusGroupInfo { + size_t refcount; /**< Reference count */ dbus_gid_t gid; /**< GID */ char *groupname; /**< Group name */ }; diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c index 44a1a78c..170d233e 100644 --- a/dbus/dbus-userdb-util.c +++ b/dbus/dbus-userdb-util.c @@ -38,6 +38,15 @@ * @{ */ +static DBusGroupInfo * +_dbus_group_info_ref (DBusGroupInfo *info) +{ + _dbus_assert (info->refcount > 0); + _dbus_assert (info->refcount < SIZE_MAX); + info->refcount++; + return info; +} + /** * Checks to see if the UID sent in is the console user * @@ -240,9 +249,9 @@ _dbus_get_user_id_and_primary_group (const DBusString *username, * @param gid the group ID or #DBUS_GID_UNSET * @param groupname group name or #NULL * @param error error to fill in - * @returns the entry in the database + * @returns the entry in the database (borrowed, do not free) */ -DBusGroupInfo* +const DBusGroupInfo * _dbus_user_database_lookup_group (DBusUserDatabase *db, dbus_gid_t gid, const DBusString *groupname, @@ -287,13 +296,14 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } + info->refcount = 1; if (gid != DBUS_GID_UNSET) { if (!_dbus_group_info_fill_gid (info, gid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_group_info_free_allocated (info); + _dbus_group_info_unref (info); return NULL; } } @@ -302,7 +312,7 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, if (!_dbus_group_info_fill (info, groupname, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_group_info_free_allocated (info); + _dbus_group_info_unref (info); return NULL; } } @@ -311,23 +321,37 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, gid = DBUS_GID_UNSET; groupname = NULL; - if (!_dbus_hash_table_insert_uintptr (db->groups, info->gid, info)) + if (_dbus_hash_table_insert_uintptr (db->groups, info->gid, info)) + { + _dbus_group_info_ref (info); + } + else { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - _dbus_group_info_free_allocated (info); + _dbus_group_info_unref (info); return NULL; } - if (!_dbus_hash_table_insert_string (db->groups_by_name, - info->groupname, - info)) + if (_dbus_hash_table_insert_string (db->groups_by_name, + info->groupname, + info)) + { + _dbus_group_info_ref (info); + } + else { _dbus_hash_table_remove_uintptr (db->groups, info->gid); + _dbus_group_info_unref (info); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } - + + /* Release the original reference */ + _dbus_group_info_unref (info); + + /* Return a borrowed reference to the DBusGroupInfo owned by the + * two hash tables */ return info; } } diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c index 4c42b7dd..10434bbb 100644 --- a/dbus/dbus-userdb.c +++ b/dbus/dbus-userdb.c @@ -35,34 +35,57 @@ * @{ */ +static DBusUserInfo * +_dbus_user_info_ref (DBusUserInfo *info) +{ + _dbus_assert (info->refcount > 0); + _dbus_assert (info->refcount < SIZE_MAX); + info->refcount++; + return info; +} + /** - * Frees the given #DBusUserInfo's members with _dbus_user_info_free() + * Decrements the reference count. If it reaches 0, + * frees the given #DBusUserInfo's members with _dbus_user_info_free() * and also calls dbus_free() on the block itself * * @param info the info */ void -_dbus_user_info_free_allocated (DBusUserInfo *info) +_dbus_user_info_unref (DBusUserInfo *info) { if (info == NULL) /* hash table will pass NULL */ return; + _dbus_assert (info->refcount > 0); + _dbus_assert (info->refcount < SIZE_MAX); + + if (--info->refcount > 0) + return; + _dbus_user_info_free (info); dbus_free (info); } /** - * Frees the given #DBusGroupInfo's members with _dbus_group_info_free() + * Decrements the reference count. If it reaches 0, + * frees the given #DBusGroupInfo's members with _dbus_group_info_free() * and also calls dbus_free() on the block itself * * @param info the info */ void -_dbus_group_info_free_allocated (DBusGroupInfo *info) +_dbus_group_info_unref (DBusGroupInfo *info) { if (info == NULL) /* hash table will pass NULL */ return; + _dbus_assert (info->refcount > 0); + _dbus_assert (info->refcount < SIZE_MAX); + + if (--info->refcount > 0) + return; + _dbus_group_info_free (info); dbus_free (info); } @@ -122,9 +145,9 @@ _dbus_is_a_number (const DBusString *str, * @param uid the user ID or #DBUS_UID_UNSET * @param username username or #NULL * @param error error to fill in - * @returns the entry in the database + * @returns the entry in the database (borrowed, do not free) */ -DBusUserInfo* +const DBusUserInfo * _dbus_user_database_lookup (DBusUserDatabase *db, dbus_uid_t uid, const DBusString *username, @@ -170,13 +193,14 @@ _dbus_user_database_lookup (DBusUserDatabase *db, dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } + info->refcount = 1; if (uid != DBUS_UID_UNSET) { if (!_dbus_user_info_fill_uid (info, uid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_user_info_free_allocated (info); + _dbus_user_info_unref (info); return NULL; } } @@ -185,7 +209,7 @@ _dbus_user_database_lookup (DBusUserDatabase *db, if (!_dbus_user_info_fill (info, username, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_user_info_free_allocated (info); + _dbus_user_info_unref (info); return NULL; } } @@ -195,22 +219,35 @@ _dbus_user_database_lookup (DBusUserDatabase *db, username = NULL; /* insert into hash */ - if (!_dbus_hash_table_insert_uintptr (db->users, info->uid, info)) + if (_dbus_hash_table_insert_uintptr (db->users, info->uid, info)) + { + _dbus_user_info_ref (info); + } + else { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - _dbus_user_info_free_allocated (info); + _dbus_user_info_unref (info); return NULL; } - if (!_dbus_hash_table_insert_string (db->users_by_name, - info->username, - info)) + if (_dbus_hash_table_insert_string (db->users_by_name, + info->username, + info)) + { + _dbus_user_info_ref (info); + } + else { _dbus_hash_table_remove_uintptr (db->users, info->uid); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + _dbus_user_info_unref (info); return NULL; } - + + _dbus_user_info_unref (info); + + /* Return a borrowed pointer to the DBusUserInfo owned by the + * hash tables */ return info; } } @@ -568,24 +605,24 @@ _dbus_user_database_new (void) db->refcount = 1; db->users = _dbus_hash_table_new (DBUS_HASH_UINTPTR, - NULL, (DBusFreeFunction) _dbus_user_info_free_allocated); + NULL, (DBusFreeFunction) _dbus_user_info_unref); if (db->users == NULL) goto failed; db->groups = _dbus_hash_table_new (DBUS_HASH_UINTPTR, - NULL, (DBusFreeFunction) _dbus_group_info_free_allocated); + NULL, (DBusFreeFunction) _dbus_group_info_unref); if (db->groups == NULL) goto failed; db->users_by_name = _dbus_hash_table_new (DBUS_HASH_STRING, - NULL, NULL); + NULL, (DBusFreeFunction) _dbus_user_info_unref); if (db->users_by_name == NULL) goto failed; db->groups_by_name = _dbus_hash_table_new (DBUS_HASH_STRING, - NULL, NULL); + NULL, (DBusFreeFunction) _dbus_group_info_unref); if (db->groups_by_name == NULL) goto failed; diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h index 53fc90b5..b38e3d18 100644 --- a/dbus/dbus-userdb.h +++ b/dbus/dbus-userdb.h @@ -76,19 +76,19 @@ dbus_bool_t _dbus_user_database_get_groupname (DBusUserDatabase *db, DBusError *error); DBUS_PRIVATE_EXPORT -DBusUserInfo* _dbus_user_database_lookup (DBusUserDatabase *db, +const DBusUserInfo *_dbus_user_database_lookup (DBusUserDatabase *db, dbus_uid_t uid, const DBusString *username, DBusError *error); DBUS_PRIVATE_EXPORT -DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db, - dbus_gid_t gid, - const DBusString *groupname, - DBusError *error); -DBUS_PRIVATE_EXPORT -void _dbus_user_info_free_allocated (DBusUserInfo *info); +const DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db, + dbus_gid_t gid, + const DBusString *groupname, + DBusError *error); + +void _dbus_user_info_unref (DBusUserInfo *info); DBUS_PRIVATE_EXPORT -void _dbus_group_info_free_allocated (DBusGroupInfo *info); +void _dbus_group_info_unref (DBusGroupInfo *info); #endif /* DBUS_USERDB_INCLUDES_PRIVATE */ DBUS_PRIVATE_EXPORT diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in index 960da080..b6cda2f6 100644 --- a/doc/dbus-daemon.1.xml.in +++ b/doc/dbus-daemon.1.xml.in @@ -267,7 +267,7 @@ DBUS_STARTER_BUS_TYPE environment variable will be set to "session" and the DBUS_SESSION_BUS_ADDRESS environment variable will be set to the address of the session bus. Likewise, if the type of the message bus is "system", then the DBUS_STARTER_BUS_TYPE environment -variable will be set to "system" and the DBUS_SESSION_BUS_ADDRESS +variable will be set to "system" and the DBUS_SYSTEM_BUS_ADDRESS environment variable will be set to the address of the system bus (which is normally well known anyway).</para> diff --git a/doc/dbus-send.1.xml.in b/doc/dbus-send.1.xml.in index 271435ca..34c4b99e 100644 --- a/doc/dbus-send.1.xml.in +++ b/doc/dbus-send.1.xml.in @@ -21,7 +21,7 @@ <refsynopsisdiv id='synopsis'> <cmdsynopsis> <command>dbus-send</command> - <group choice='opt'><arg choice='plain'>--system </arg><arg choice='plain'>--session </arg><arg choice='plain'>--address=<replaceable>ADDRESS</replaceable></arg></group> + <group choice='opt'><arg choice='plain'>--system </arg><arg choice='plain'>--session </arg><arg choice='plain'>--bus=<replaceable>ADDRESS</replaceable></arg><arg choice='plain'>--peer=<replaceable>ADDRESS</replaceable></arg></group> <arg choice='opt'>--dest=<replaceable>NAME</replaceable></arg> <arg choice='opt'><arg choice='plain'>--print-reply </arg><arg choice='opt'><replaceable>=literal</replaceable></arg></arg> <arg choice='opt'>--reply-timeout=<replaceable>MSEC</replaceable></arg> @@ -137,9 +137,15 @@ The default is implementation‐defined, typically 25 seconds.</para> </listitem> </varlistentry> <varlistentry> - <term><option>--address=</option><replaceable>ADDRESS</replaceable></term> + <term><option>--bus=</option><replaceable>ADDRESS</replaceable></term> <listitem> -<para>Send to <replaceable>ADDRESS</replaceable>.</para> +<para>Register on a message bus at <replaceable>ADDRESS</replaceable>, typically a <command>dbus-daemon</command>.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>--peer=</option><replaceable>ADDRESS</replaceable></term> + <listitem> +<para>Send to a non-message-bus D-Bus server at <replaceable>ADDRESS</replaceable>. In this case <command>dbus-send</command> will not call the <literal>Hello</literal> method.</para> </listitem> </varlistentry> <varlistentry> diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index 7d3bb4b2..d753d831 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -2040,6 +2040,7 @@ test_fd_limit (Fixture *f, { #ifdef HAVE_PRLIMIT struct rlimit lim; + struct rlimit new_limit; const struct passwd *pwd = NULL; #endif @@ -2067,7 +2068,7 @@ test_fd_limit (Fixture *f, } if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0) - g_error ("prlimit(): %s", g_strerror (errno)); + g_error ("get prlimit (self): %s", g_strerror (errno)); g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld", (long) lim.rlim_cur, (long) lim.rlim_max); @@ -2079,8 +2080,33 @@ test_fd_limit (Fixture *f, return; } + new_limit = lim; + new_limit.rlim_cur = DESIRED_RLIMIT; + new_limit.rlim_max = DESIRED_RLIMIT; + + /* Try to increase the rlimit ourselves. If we're root in an + * unprivileged Linux container, then we won't have CAP_SYS_RESOURCE + * and this will fail with EPERM. If so, the dbus-daemon wouldn't be + * able to increase its rlimit either. */ + if (prlimit (getpid (), RLIMIT_NOFILE, &new_limit, NULL) < 0) + { + gchar *message; + + message = g_strdup_printf ("Cannot test, we cannot change the rlimit so " + "presumably neither can the dbus-daemon: %s", + g_strerror (errno)); + g_test_skip (message); + g_free (message); + return; + } + + /* Immediately put our original limit back so it won't interfere with + * subsequent tests. This should always succeed. */ + if (prlimit (getpid (), RLIMIT_NOFILE, &lim, NULL) < 0) + g_error ("Cannot restore our original limits: %s", g_strerror (errno)); + if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0) - g_error ("prlimit(): %s", g_strerror (errno)); + g_error ("get prlimit (dbus-daemon): %s", g_strerror (errno)); g_test_message ("dbus-daemon's RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld", (long) lim.rlim_cur, (long) lim.rlim_max); diff --git a/test/fdpass.c b/test/fdpass.c index 4a3edc4e..8bad675f 100644 --- a/test/fdpass.c +++ b/test/fdpass.c @@ -50,6 +50,14 @@ #include "test-utils-glib.h" +#ifdef DBUS_ENABLE_EMBEDDED_TESTS +#include <dbus/dbus-message-internal.h> +#else +typedef struct _DBusInitialFDs DBusInitialFDs; +#define _dbus_check_fdleaks_enter() NULL +#define _dbus_check_fdleaks_leave(fds) do {} while (0) +#endif + /* Arbitrary; included here to avoid relying on the default */ #define MAX_MESSAGE_UNIX_FDS 20 /* This test won't work on Linux unless this is true. */ @@ -92,6 +100,7 @@ typedef struct { GQueue messages; int fd_before; + DBusInitialFDs *initial_fds; } Fixture; static void oom (const gchar *doing) G_GNUC_NORETURN; @@ -176,6 +185,8 @@ test_connect (Fixture *f, if (f->skip) return; + f->initial_fds = _dbus_check_fdleaks_enter (); + g_assert (f->left_server_conn == NULL); g_assert (f->right_server_conn == NULL); @@ -871,6 +882,9 @@ teardown (Fixture *f, if (f->fd_before >= 0 && close (f->fd_before) < 0) g_error ("%s", g_strerror (errno)); #endif + + if (f->initial_fds != NULL) + _dbus_check_fdleaks_leave (f->initial_fds); } int |