Merge "Merge '1.12.20' into tizen" into tizen
authorHyotaek Shim <hyotaek.shim@samsung.com>
Wed, 4 Nov 2020 08:21:43 +0000 (08:21 +0000)
committerGerrit Code Review <gerrit@review>
Wed, 4 Nov 2020 08:21:43 +0000 (08:21 +0000)
15 files changed:
NEWS
bus/connection.c
cmake/tools/CMakeLists.txt
configure.ac
dbus/dbus-message.c
dbus/dbus-sysdeps-unix.c
dbus/dbus-sysdeps-unix.h
dbus/dbus-userdb-util.c
dbus/dbus-userdb.c
dbus/dbus-userdb.h
doc/dbus-daemon.1.xml.in
doc/dbus-send.1.xml.in
packaging/dbus.spec
test/dbus-daemon.c
test/fdpass.c

diff --git a/NEWS b/NEWS
index 07a933a..2fca145 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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)
 =========================
 
index 6b85ba3..78948c6 100644 (file)
@@ -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),
index c05ced4..4678bdd 100644 (file)
@@ -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
index e7d8d38..20c821a 100644 (file)
@@ -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
index 7fec313..7d44a2e 100644 (file)
@@ -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
index e8cd5b3..e511afc 100644 (file)
@@ -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);
 
index 8d3df2d..830d5cd 100644 (file)
@@ -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 */
 };
index 44a1a78..170d233 100644 (file)
  * @{
  */
 
+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;
     }
 }
index 4c42b7d..10434bb 100644 (file)
  * @{
  */
 
+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;
   
index 53fc90b..b38e3d1 100644 (file)
@@ -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
index 960da08..b6cda2f 100644 (file)
@@ -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>
 
index 271435c..34c4b99 100644 (file)
@@ -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&hyphen;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>
index 93db9c1..a1ccefa 100644 (file)
@@ -26,7 +26,7 @@ BuildRequires:  pkgconfig(cynara-client)
 BuildRequires:  pkgconfig(cynara-session)
 BuildRequires:  pkgconfig(cynara-client-async)
 BuildRequires:  pkgconfig(libdbuspolicy1)
-Version:        1.12.16
+Version:        1.12.20
 Release:        3
 Source0:        http://dbus.freedesktop.org/releases/dbus/dbus-%{version}.tar.gz
 Source3:        dbus_at_console.ck
index 7d3bb4b..d753d83 100644 (file)
@@ -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);
index 4a3edc4..8bad675 100644 (file)
 
 #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